105 lines
4.7 KiB
C#
105 lines
4.7 KiB
C#
|
//---------------------------------------------------------------------
|
|||
|
// <copyright file="SnapshotChangeTrackingStrategy.cs" company="Microsoft">
|
|||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|||
|
// </copyright>
|
|||
|
//---------------------------------------------------------------------
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Text;
|
|||
|
using System.Data.Objects.DataClasses;
|
|||
|
|
|||
|
namespace System.Data.Objects.Internal
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Implementation of the change tracking strategy for entities that require snapshot change tracking.
|
|||
|
/// These are typically entities that do not implement IEntityWithChangeTracker.
|
|||
|
/// </summary>
|
|||
|
internal sealed class SnapshotChangeTrackingStrategy : IChangeTrackingStrategy
|
|||
|
{
|
|||
|
private static SnapshotChangeTrackingStrategy _instance = new SnapshotChangeTrackingStrategy();
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Returns the single static instance of this class; a single instance is all that is needed
|
|||
|
/// because the class is stateless.
|
|||
|
/// </summary>
|
|||
|
public static SnapshotChangeTrackingStrategy Instance
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return _instance;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Private constructor to help prevent additional instances being created.
|
|||
|
private SnapshotChangeTrackingStrategy()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
// See IChangeTrackingStrategy documentation
|
|||
|
public void SetChangeTracker(IEntityChangeTracker changeTracker)
|
|||
|
{
|
|||
|
// Nothing to do when using snapshots for change tracking
|
|||
|
}
|
|||
|
|
|||
|
// See IChangeTrackingStrategy documentation
|
|||
|
public void TakeSnapshot(EntityEntry entry)
|
|||
|
{
|
|||
|
if (entry != null)
|
|||
|
{
|
|||
|
entry.TakeSnapshot(false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// See IChangeTrackingStrategy documentation
|
|||
|
public void SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, int ordinal, object target, object value)
|
|||
|
{
|
|||
|
// If the target is the entity, then this is a change to a member on the entity itself rather than
|
|||
|
// a change to some complex type property defined on the entity. In this case we can use the change tracking
|
|||
|
// API in the normal way.
|
|||
|
if (Object.ReferenceEquals(target, entry.Entity))
|
|||
|
{
|
|||
|
// equivalent of EntityObject.ReportPropertyChanging()
|
|||
|
((IEntityChangeTracker)entry).EntityMemberChanging(member.CLayerName);
|
|||
|
member.SetValue(target, value);
|
|||
|
// equivalent of EntityObject.ReportPropertyChanged()
|
|||
|
((IEntityChangeTracker)entry).EntityMemberChanged(member.CLayerName);
|
|||
|
|
|||
|
if (member.IsComplex)
|
|||
|
{
|
|||
|
// This is required because the OSE contains a separate cache of user objects for
|
|||
|
// complex objects such that original values can be looked up correctly.
|
|||
|
entry.UpdateComplexObjectSnapshot(member, target, ordinal, value);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Must be a complex type. We would like to do this:
|
|||
|
// ((IEntityChangeTracker)entry).EntityComplexMemberChanging(topLevelMember.CLayerName, target, member.CLayerName);
|
|||
|
// ((IEntityChangeTracker)entry).EntityComplexMemberChanged(topLevelMember.CLayerName, target, member.CLayerName);
|
|||
|
//
|
|||
|
// However, we have no way of getting the topLevelMember.CLayerName. This is because the value record does not
|
|||
|
// contain any reference to its parent. (In non-POCO, ComplexObject takes care of this.)
|
|||
|
// Therefore, in this case we are going to just call a localized DetectChanges to make sure that changes in the
|
|||
|
// complex types are found.
|
|||
|
//
|
|||
|
// Note that this case only happens when the entity is POCO and complex types are set through the CurrentValues
|
|||
|
// object. This is probably not a very common pattern.
|
|||
|
member.SetValue(target, value);
|
|||
|
if (entry.State != EntityState.Added)
|
|||
|
{
|
|||
|
// Entry is not Detached - checked in ValidateState() in EntityEntry.SetCurrentEntityValue
|
|||
|
entry.DetectChangesInProperties(true);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// See IChangeTrackingStrategy documentation
|
|||
|
public void UpdateCurrentValueRecord(object value, EntityEntry entry)
|
|||
|
{
|
|||
|
// No change tracker, but may or may not be a proxy
|
|||
|
entry.UpdateRecordWithoutSetModified(value, entry.CurrentValues);
|
|||
|
entry.DetectChangesInProperties(false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|