C# 实体框架代码优先和实体跟踪

C# 实体框架代码优先和实体跟踪,c#,.net,entity-framework,ef-code-first,C#,.net,Entity Framework,Ef Code First,假设您有一个在业务层中创建的纯POCO对象(例如,Customer),然后调用context.Add(Customer)。您传入并引用的Customer对象是否会被更改跟踪?换句话说:您传递的对象是与被ObjectStateManager跟踪的对象相同还是不同 如果它们不是同一个对象,会不会导致大量内存消耗,因为有两个对象图一直在维护:一个由业务层的您(开发人员)维护,另一个由DAL中的ObjectStateManager维护?上下文的思想是不要让它变得太大。甚至有多个具有不同数据视图的上下文。

假设您有一个在业务层中创建的纯POCO对象(例如,
Customer
),然后调用
context.Add(Customer)
。您传入并引用的
Customer
对象是否会被更改跟踪?换句话说:您传递的对象是与被
ObjectStateManager
跟踪的对象相同还是不同


如果它们不是同一个对象,会不会导致大量内存消耗,因为有两个对象图一直在维护:一个由业务层的您(开发人员)维护,另一个由DAL中的
ObjectStateManager
维护?

上下文的思想是不要让它变得太大。甚至有多个具有不同数据视图的上下文。甚至可以在每个工作单元中使用新的上下文。 所以是的,它可以变大。关于这个话题的一些好的读物 搜索有界上下文和Luw模式。如朱莉·勒曼

以下是由EF管理的反编译的IEntityWrapper(来自EF5.0/NET4.0) 在ObjectContext中放置实体时使用IENtityWrapper

我让你决定它是否大。
正如Millric所提到的,引用是
对象实体{get;}//请参见下面的内部包装

internal interface IEntityWrapper
{
void EnsureCollectionNotNull(RelatedEnd relatedEnd);
EntityKey GetEntityKeyFromEntity();
void AttachContext(ObjectContext context, EntitySet entitySet, MergeOption mergeOption);
void ResetContext(ObjectContext context, EntitySet entitySet, MergeOption mergeOption);
void DetachContext();
void SetChangeTracker(IEntityChangeTracker changeTracker);
void TakeSnapshot(EntityEntry entry);
void TakeSnapshotOfRelationships(EntityEntry entry);
void CollectionAdd(RelatedEnd relatedEnd, object value);
bool CollectionRemove(RelatedEnd relatedEnd, object value);
object GetNavigationPropertyValue(RelatedEnd relatedEnd);
void SetNavigationPropertyValue(RelatedEnd relatedEnd, object value);
void RemoveNavigationPropertyValue(RelatedEnd relatedEnd, object value);
void SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, int ordinal, object target, object value);
void UpdateCurrentValueRecord(object value, EntityEntry entry);
RelationshipManager RelationshipManager { get; }
bool OwnsRelationshipManager { get; }
object Entity { get; }
EntityEntry ObjectStateEntry { get; set; }
EntityKey EntityKey { get; set; }
ObjectContext Context { get; set; }
MergeOption MergeOption { get; }
Type IdentityType { get; }
bool InitializingProxyRelatedEnds { get; set; }
bool RequiresRelationshipChangeTracking { get; }
} 



/// <summary>
/// Adds an object to the object context.
/// </summary>
/// <param name="entitySetName">Represents the entity set name, which may optionally be qualified by the entity container name. </param><param name="entity">The <see cref="T:System.Object"/> to add.</param><exception cref="T:System.ArgumentNullException">The <paramref name="entity"/> parameter is null. -or-The <paramref name="entitySetName"/> does not qualify.</exception>
public void AddObject(string entitySetName, object entity)
{
  EntityUtil.CheckArgumentNull<object>(entity, "entity");
  EntityEntry existingEntry;
  IEntityWrapper wrappedEntity = EntityWrapperFactory.WrapEntityUsingContextGettingEntry(entity, this, out existingEntry);
  if (existingEntry == null)
    this.MetadataWorkspace.ImplicitLoadAssemblyForType(wrappedEntity.IdentityType, (Assembly) null);
  EntitySet entitySet;
  bool isNoOperation;
  this.VerifyRootForAdd(false, entitySetName, wrappedEntity, existingEntry, out entitySet, out isNoOperation);
  if (isNoOperation)
    return;
  System.Data.Objects.Internal.TransactionManager transactionManager = this.ObjectStateManager.TransactionManager;
  transactionManager.BeginAddTracking();
  try
  {
    RelationshipManager relationshipManager = wrappedEntity.RelationshipManager;
    bool flag = true;
    try
    {
      this.AddSingleObject(entitySet, wrappedEntity, "entity");
      flag = false;
    }
    finally
    {
      if (flag && wrappedEntity.Context == this)
      {
        EntityEntry entityEntry = this.ObjectStateManager.FindEntityEntry(wrappedEntity.Entity);
        if (entityEntry != null && entityEntry.EntityKey.IsTemporary)
        {
          relationshipManager.NodeVisited = true;
          RelationshipManager.RemoveRelatedEntitiesFromObjectStateManager(wrappedEntity);
          RelatedEnd.RemoveEntityFromObjectStateManager(wrappedEntity);
        }
      }
    }
    relationshipManager.AddRelatedEntitiesToObjectStateManager(false);
  }
  finally
  {
    transactionManager.EndAddTracking();
  }
}
内部接口IEntityWrapper
{
void conferelectionnotnull(RelatedEnd RelatedEnd);
EntityKey GetEntityKeyFromEntity();
void AttachContext(ObjectContext上下文、EntitySet EntitySet、MergeOption MergeOption);
void ResetContext(ObjectContext上下文、EntitySet EntitySet、MergeOption MergeOption);
void DetachContext();
void SetChangeTracker(IEntityChangeTracker-changeTracker);
作废快照(EntityEntry);
关系的无效快照(实体条目);
void CollectionAdd(RelatedEnd RelatedEnd,对象值);
bool CollectionRemove(RelatedEnd RelatedEnd,对象值);
对象GetNavigationPropertyValue(RelatedEnd RelatedEnd);
void SetNavigationPropertyValue(RelatedEnd RelatedEnd,对象值);
void RemoveNavigationPropertyValue(RelatedEnd RelatedEnd,对象值);
void SetCurrentValue(EntityEntry条目、StateManagerMemberMetadata成员、整数序号、对象目标、对象值);
作废UpdateCurrentValueRecord(对象值,EntityEntry);
RelationshipManager RelationshipManager{get;}
bool OwnsRelationshipManager{get;}
对象实体{get;}
EntityEntry ObjectStateEntry{get;set;}
EntityKey EntityKey{get;set;}
ObjectContext上下文{get;set;}
合并选项合并选项{get;}
类型标识类型{get;}
bool initializeProxyRelatedEnds{get;set;}
bool RequiresRelationshipChangeTracking{get;}
} 
/// 
///将对象添加到对象上下文中。
/// 
///表示实体集名称,该名称可以由实体容器名称限定。要添加的参数。参数为null-或者,这项技术不合格。
public void AddObject(字符串entitySetName,对象实体)
{
EntityUtil.CheckArgumentNull(实体,“实体”);
实体条目现有条目;
IEntityWrapper wrappedEntity=EntityWrapperFactory.WrappentityUsingContextGettingEntry(entity,this,out existingEntry);
if(existingEntry==null)
this.MetadataWorkspace.ImplicitLoadAssemblyForType(wrappedEntity.IdentityType,(Assembly)null);
EntitySet-EntitySet;
布尔是无操作的;
此.VerifyRootForAdd(false、entitySetName、wrappedEntity、existingEntry、out entitySet、out isNoOperation);
if(isNoOperation)
返回;
System.Data.Objects.Internal.TransactionManager TransactionManager=this.ObjectStateManager.TransactionManager;
transactionManager.BeginAddTracking();
尝试
{
RelationshipManager RelationshipManager=wrappedEntity.RelationshipManager;
布尔标志=真;
尝试
{
this.AddSingleObject(entitySet,wrappedEntity,“entity”);
flag=false;
}
最后
{
if(flag&&wrappedEntity.Context==this)
{
EntityEntry EntityEntry=this.ObjectStateManager.FindentialEntry(wrappedEntity.Entity);
if(entityEntry!=null&&entityEntry.EntityKey.IsTemporary)
{
relationshipManager.NodeVisited=true;
RelationshipManager。从ObjectStateManager(wrappedEntity)中删除关联性;
RelatedEnd.RemoveEntityFromObjectStateManager(wrappedEntity);
}
}
}
relationshipManager.AddRelatedEntities到ObjectStateManager(false);
}
最后
{
transactionManager.EndAddTracking();
}
}

这篇文章进一步解释了如何使用POCO进行更改跟踪@MalcolmO'Hare,我浏览了这篇文章,但我似乎没有谈论这个特殊的案例。这回答了第二部分,但是第一部分呢?添加是默认跟踪的更改。对象被引用但未被复制,但我尝试比较我为插入传递的对象与ObjectStateManager中的对象之间的引用,它们不相同。真的,它是在引用之前克隆的吗?好的,谢谢。一直认为这是一个真正的参考。该调试了。//我刚刚运行了一个测试,测试显示使用了相同的对象。var t1=新租户();var g=Guid.NewGuid();t1.Id=g;t1.FirstName=“我的名字是”;uluw.Context.Set().Add(t1);t1.LastName=“打印时参考相同”;var t2=uluw.Context.Set().Local.Where(ten=>ten.Id==g.FirstOrDefault();Console.WriteLine(t2.LastName);