0

Say you have a pure POCO object (eg. Customer) that you have created in the business layer and then called context.Add(customer). Would the Customer object that you have passed in, and have reference to, be change tracked? Put another way: is the object you passed in the same one that is being tracked by the ObjectStateManager or is it a different one?

If they aren't the same object, wouldn't that lead to large memory consumption because there are two object graphs being maintained all the time: one by you (developer) in the business layer and the other by the ObjectStateManager in the DAL?

4

1 回答 1

0

The Idea of the Context is to not let it get too large. To even have multiple contexts with different views of the data. Even going as far as using a new context per Unit of Work. So yes it can get large. Some good reading on this topic Search for Bounded Contexts and Luw Pattern. eg from Julie Lerman.

Here is the decompiled IEntityWrapper managed by EF (from EF5.0 / Net 4.0) IENtityWrapper is used when putting an Entity in the ObjectContext.

I let you decide if it is big.
AS mentioned by Millimetric the reference is object Entity { get; } // see below inside wrapper

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();
  }
}
于 2012-12-17T15:37:50.923 回答