コード例 #1
0
        private static Func <object, IEntityWrapper> CreateWrapperDelegate(Type entityType)
        {
            // For entities that implement all our interfaces we create a special lightweight wrapper that is both
            // smaller and faster than the strategy-based wrapper.
            // Otherwise, the wrapper is provided with different delegates depending on which interfaces are implemented.
            bool       isIEntityWithRelationships = typeof(IEntityWithRelationships).IsAssignableFrom(entityType);
            bool       isIEntityWithChangeTracker = typeof(IEntityWithChangeTracker).IsAssignableFrom(entityType);
            bool       isIEntityWithKey           = typeof(IEntityWithKey).IsAssignableFrom(entityType);
            bool       isProxy = EntityProxyFactory.IsProxyType(entityType);
            MethodInfo createDelegate;

            if (isIEntityWithRelationships && isIEntityWithChangeTracker && isIEntityWithKey && !isProxy)
            {
                createDelegate = typeof(EntityWrapperFactory).GetMethod("CreateWrapperDelegateTypedLightweight", BindingFlags.NonPublic | BindingFlags.Static);
            }
            else if (isIEntityWithRelationships)
            {
                // This type of strategy wrapper is used when the entity implements IEntityWithRelationships
                // In this case it is important that the entity itself is used to create the RelationshipManager
                createDelegate = typeof(EntityWrapperFactory).GetMethod("CreateWrapperDelegateTypedWithRelationships", BindingFlags.NonPublic | BindingFlags.Static);
            }
            else
            {
                createDelegate = typeof(EntityWrapperFactory).GetMethod("CreateWrapperDelegateTypedWithoutRelationships", BindingFlags.NonPublic | BindingFlags.Static);
            }
            createDelegate = createDelegate.MakeGenericMethod(entityType);
            return((Func <object, IEntityWrapper>)createDelegate.Invoke(null, new object[0]));
        }
コード例 #2
0
 // See IPropertyAccessorStrategy
 public void SetNavigationPropertyValue(RelatedEnd relatedEnd, object value)
 {
     if (relatedEnd != null)
     {
         if (relatedEnd.TargetAccessor.ValueSetter == null)
         {
             Type         type         = GetDeclaringType(relatedEnd);
             PropertyInfo propertyInfo = EntityUtil.GetTopProperty(ref type, relatedEnd.TargetAccessor.PropertyName);
             if (propertyInfo == null)
             {
                 throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, type.FullName));
             }
             EntityProxyFactory factory = new EntityProxyFactory();
             relatedEnd.TargetAccessor.ValueSetter = factory.CreateBaseSetter(type, propertyInfo);
         }
         try
         {
             relatedEnd.TargetAccessor.ValueSetter(_entity, value);
         }
         catch (Exception ex)
         {
             throw new EntityException(System.Data.Entity.Strings.PocoEntityWrapper_UnableToSetFieldOrProperty(relatedEnd.TargetAccessor.PropertyName, _entity.GetType().FullName), ex);
         }
     }
 }
コード例 #3
0
        /// <summary>
        /// Called to create a new wrapper outside of the normal materialization process.
        /// This method is typically used when a new entity is created outside the context and then is
        /// added or attached.  The materializer bypasses this method and calls wrapper constructors
        /// directory for performance reasons.
        /// This method does not check whether or not the wrapper already exists in the context.
        /// </summary>
        /// <param name="entity">The entity for which a wrapper will be created</param>
        /// <param name="key">The key associated with that entity, or null</param>
        /// <returns>The new wrapper instance</returns>
        internal static IEntityWrapper CreateNewWrapper(object entity, EntityKey key)
        {
            Debug.Assert(!(entity is IEntityWrapper), "Object is an IEntityWrapper instance instead of the raw entity.");
            if (entity == null)
            {
                return(NullEntityWrapper.NullWrapper);
            }
            // We used a cache of functions based on the actual type of entity that we need to wrap.
            // Creatung these functions is slow, but once they are created they are relatively fast.
            IEntityWrapper wrappedEntity = _delegateCache.Evaluate(entity.GetType())(entity);

            wrappedEntity.RelationshipManager.SetWrappedOwner(wrappedEntity, entity);
            // We cast to object here to avoid calling the overridden != operator on EntityKey.
            // This creates a very small perf gain, which is none-the-less significant for lean no-tracking cases.
            if ((object)key != null && (object)wrappedEntity.EntityKey == null)
            {
                wrappedEntity.EntityKey = key;
            }

            // If the entity is a proxy, set the wrapper to match
            EntityProxyTypeInfo proxyTypeInfo;

            if (EntityProxyFactory.TryGetProxyType(entity.GetType(), out proxyTypeInfo))
            {
                proxyTypeInfo.SetEntityWrapper(wrappedEntity);
            }

            return(wrappedEntity);
        }
コード例 #4
0
 internal static Type GetEntityIdentityType(Type entityType)
 {
     if (!EntityProxyFactory.IsProxyType(entityType))
     {
         return(entityType);
     }
     return(entityType.BaseType());
 }
コード例 #5
0
 /// <summary>
 /// Constructs a wrapper for the given entity.
 /// Note: use EntityWrapperFactory instead of calling this constructor directly.
 /// </summary>
 /// <param name="entity">The entity to wrap</param>
 internal LightweightEntityWrapper(TEntity entity)
     : base(entity, entity.RelationshipManager)
 {
     Debug.Assert(entity is IEntityWithChangeTracker, "LightweightEntityWrapper only works with entities that implement IEntityWithChangeTracker");
     Debug.Assert(entity is IEntityWithRelationships, "LightweightEntityWrapper only works with entities that implement IEntityWithRelationships");
     Debug.Assert(entity is IEntityWithKey, "LightweightEntityWrapper only works with entities that implement IEntityWithKey");
     Debug.Assert(!EntityProxyFactory.IsProxyType(entity.GetType()), "LightweightEntityWrapper only works with entities that are not proxies");
     _entity = entity;
 }
コード例 #6
0
 /// <summary>
 /// Constructs a wrapper as part of the materialization process.  This constructor is only used
 /// during materialization where it is known that the entity being wrapped is newly constructed.
 /// This means that some checks are not performed that might be needed when thw wrapper is
 /// created at other times, and information such as the identity type is passed in because
 /// it is readily available in the materializer.
 /// </summary>
 /// <param name="entity">The entity to wrap</param>
 /// <param name="key">The key for the entity</param>
 /// <param name="entitySet">The entity set, or null if none is known</param>
 /// <param name="context">The context to which the entity should be attached</param>
 /// <param name="mergeOption">NoTracking for non-tracked entities, AppendOnly otherwise</param>
 /// <param name="identityType">The type of the entity ignoring any possible proxy type</param>
 internal LightweightEntityWrapper(TEntity entity, EntityKey key, EntitySet entitySet, ObjectContext context, MergeOption mergeOption, Type identityType)
     : base(entity, entity.RelationshipManager, entitySet, context, mergeOption, identityType)
 {
     Debug.Assert(entity is IEntityWithChangeTracker, "LightweightEntityWrapper only works with entities that implement IEntityWithChangeTracker");
     Debug.Assert(entity is IEntityWithRelationships, "LightweightEntityWrapper only works with entities that implement IEntityWithRelationships");
     Debug.Assert(entity is IEntityWithKey, "LightweightEntityWrapper only works with entities that implement IEntityWithKey");
     Debug.Assert(!EntityProxyFactory.IsProxyType(entity.GetType()), "LightweightEntityWrapper only works with entities that are not proxies");
     _entity           = entity;
     _entity.EntityKey = key;
 }
コード例 #7
0
        /// <summary>
        /// 注册实体代理类型
        /// </summary>
        /// <param name="result"></param>
        internal static void RegisterCompileResult(List <EntityCompileResult> result)
        {
            if (result == null || result.Count == 0)
            {
                return;
            }

            // 【实体代理类型】允许为空,所以要过滤
            List <Type>   proxyTypes      = (from x in result where x.ProxyType != null select x.ProxyType).ToList();
            List <object> loaderInstances = (from x in result select x.LoaderInstnace).ToList();

            EntityProxyFactory.BatchRegister(proxyTypes);
            DataLoaderFactory.BatchRegister(loaderInstances);
        }
コード例 #8
0
        public void Test_EntityProxyFactory_Register()
        {
            Product product = Entity.BeginEdit <Product>();
            Type    t1      = product.GetType();

            Assert.AreEqual(typeof(Product), t1.BaseType);


            // 覆盖初始化时的注册,结果其实是一样的
            EntityProxyFactory.Register(t1);

            Product product2 = Entity.BeginEdit <Product>();
            Type    t2       = product2.GetType();

            Assert.AreEqual(typeof(Product), t2.BaseType);
            Assert.AreEqual(t1, t2);
        }
コード例 #9
0
        // Creates delegates that create strategy objects appropriate for the type of entity.
        private static void CreateStrategies <TEntity>(out Func <object, IPropertyAccessorStrategy> createPropertyAccessorStrategy,
                                                       out Func <object, IChangeTrackingStrategy> createChangeTrackingStrategy,
                                                       out Func <object, IEntityKeyStrategy> createKeyStrategy)
        {
            Type entityType = typeof(TEntity);
            bool isIEntityWithRelationships = typeof(IEntityWithRelationships).IsAssignableFrom(entityType);
            bool isIEntityWithChangeTracker = typeof(IEntityWithChangeTracker).IsAssignableFrom(entityType);
            bool isIEntityWithKey           = typeof(IEntityWithKey).IsAssignableFrom(entityType);
            bool isProxy = EntityProxyFactory.IsProxyType(entityType);

            if (!isIEntityWithRelationships || isProxy)
            {
                createPropertyAccessorStrategy = GetPocoPropertyAccessorStrategyFunc();
            }
            else
            {
                createPropertyAccessorStrategy = GetNullPropertyAccessorStrategyFunc();
            }

            if (isIEntityWithChangeTracker)
            {
                createChangeTrackingStrategy = GetEntityWithChangeTrackerStrategyFunc();
            }
            else
            {
                createChangeTrackingStrategy = GetSnapshotChangeTrackingStrategyFunc();
            }

            if (isIEntityWithKey)
            {
                createKeyStrategy = GetEntityWithKeyStrategyStrategyFunc();
            }
            else
            {
                createKeyStrategy = GetPocoEntityKeyStrategyFunc();
            }
        }
コード例 #10
0
        /// <summary>
        /// Wraps an entity and returns a new wrapper, or returns an existing wrapper if one
        /// already exists in the ObjectStateManager or in a RelationshipManager associated with
        /// the entity.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="context">The state manager  in which the entity may exist, or null</param>
        /// <param name="existingEntry">The existing state entry for the given entity if one exists, otherwise null</param>
        /// <returns>A new or existing wrapper</returns>
        internal static IEntityWrapper WrapEntityUsingStateManagerGettingEntry(object entity, ObjectStateManager stateManager, out EntityEntry existingEntry)
        {
            Debug.Assert(!(entity is IEntityWrapper), "Object is an IEntityWrapper instance instead of the raw entity.");
            IEntityWrapper wrapper = null;

            existingEntry = null;

            if (entity == null)
            {
                return(NullEntityWrapper.NullWrapper);
            }
            // First attempt to find an existing wrapper in the ObjectStateMager.
            if (stateManager != null)
            {
                existingEntry = stateManager.FindEntityEntry(entity);
                if (existingEntry != null)
                {
                    return(existingEntry.WrappedEntity);
                }
                if (stateManager.TransactionManager.TrackProcessedEntities)
                {
                    if (stateManager.TransactionManager.WrappedEntities.TryGetValue(entity, out wrapper))
                    {
                        return(wrapper);
                    }
                }
            }
            // If no entity was found in the OSM, then check if one exists on an associated
            // RelationshipManager.  This only works where the entity implements IEntityWithRelationshops.
            IEntityWithRelationships entityWithRelationships = entity as IEntityWithRelationships;

            if (entityWithRelationships != null)
            {
                RelationshipManager relManager = entityWithRelationships.RelationshipManager;
                if (relManager == null)
                {
                    throw EntityUtil.UnexpectedNullRelationshipManager();
                }
                IEntityWrapper wrappedEntity = relManager.WrappedOwner;
                if (!Object.ReferenceEquals(wrappedEntity.Entity, entity))
                {
                    // This means that the owner of the RelationshipManager must have been set
                    // incorrectly in the call to RelationshipManager.Create().
                    throw EntityUtil.InvalidRelationshipManagerOwner();
                }
                return(wrappedEntity);
            }
            else
            {
                // Finally look to see if the instance is a proxy and get the wrapper from the proxy
                EntityProxyFactory.TryGetProxyWrapper(entity, out wrapper);
            }

            // If we could not find an existing wrapper, then go create a new one
            if (wrapper == null)
            {
                IEntityWithKey withKey = entity as IEntityWithKey;
                wrapper = CreateNewWrapper(entity, withKey == null ? null : withKey.EntityKey);
            }
            if (stateManager != null && stateManager.TransactionManager.TrackProcessedEntities)
            {
                stateManager.TransactionManager.WrappedEntities.Add(entity, wrapper);
            }
            return(wrapper);
        }
コード例 #11
0
 /// <summary>
 ///     Returns the Type object that should be used to identify the type in the o-space
 ///     metadata.  This is normally just the type that is passed in, but if the type
 ///     is a proxy that we have generated, then its base type is returned instead.
 ///     This ensures that both proxy entities and normal entities are treated as the
 ///     same kind of entity in the metadata and places where the metadata is used.
 /// </summary>
 internal static Type GetEntityIdentityType(Type entityType)
 {
     return(EntityProxyFactory.IsProxyType(entityType) ? entityType.BaseType : entityType);
 }