Пример #1
0
        private Dictionary <Type, List <string> > GetSets()
        {
            DbContextTypesInitializersPair setsInfo;

            if (!_objectSetInitializers.TryGetValue(_context.GetType(), out setsInfo))
            {
                var dbContextParam = Expression.Parameter(typeof(DbContext), "dbContext");
                var initDelegates  = new List <Action <DbContext> >();

                var entityTypes = new Dictionary <Type, List <string> >();

                foreach (var propertyInfo in _context.GetType().GetInstanceProperties().Where(p => p.GetIndexParameters().Length == 0 && p.DeclaringType != typeof(DbContext)))
                {
                    var entityType = GetSetType(propertyInfo.PropertyType);
                    if (entityType != null)
                    {
                        if (!entityType.IsValidStructuralType())
                        {
                            throw new InvalidOperationException(entityType.Name);
                        }

                        List <string> properties;
                        if (!entityTypes.TryGetValue(entityType, out properties))
                        {
                            properties = new List <string>();
                            entityTypes[entityType] = properties;
                        }
                        properties.Add(propertyInfo.Name);

                        var setter = propertyInfo.Setter();
                        if (setter != null && setter.IsPublic)
                        {
                            var setMethod = SetMethod.MakeGenericMethod(entityType);

                            var newExpression = Expression.Call(dbContextParam, setMethod);
                            var setExpression = Expression.Call(Expression.Convert(dbContextParam, _context.GetType()), setter, newExpression);
                            initDelegates.Add(Expression.Lambda <Action <DbContext> >(setExpression, dbContextParam).Compile());
                        }
                    }
                }

                Action <DbContext> initializer = dbContext =>
                {
                    foreach (var initer in initDelegates)
                    {
                        initer(dbContext);
                    }
                };

                setsInfo = new DbContextTypesInitializersPair(entityTypes, initializer);
                _objectSetInitializers.TryAdd(_context.GetType(), setsInfo);
                EntitySetCache.Initialize(entityTypes);
            }
            return(setsInfo.EntityTypeToPropertyNameMap);
        }
        // <summary>
        // Processes the given context type to determine the DbSet or IDbSet
        // properties and collect root entity types from those properties.  Also, delegates are
        // created to initialize any of these properties that have public setters.
        // If the type has been processed previously in the app domain, then all this information
        // is returned from a cache.
        // </summary>
        // <returns> A dictionary of potential entity type to the list of the names of the properties that used the type. </returns>
        private Dictionary<Type, List<string>> GetSets()
        {
            DbContextTypesInitializersPair setsInfo;
            if (!_objectSetInitializers.TryGetValue(_context.GetType(), out setsInfo))
            {
                // It is possible that multiple threads will enter this code and create the list
                // and the delegates.  However, the result will always be the same so we may, in
                // the rare cases in which this happens, do some work twice, but functionally the
                // outcome will be correct.

                var dbContextParam = Expression.Parameter(typeof(DbContext), "dbContext");
                var initDelegates = new List<Action<DbContext>>();

                var entityTypes = new Dictionary<Type, List<string>>();

                // Properties declared directly on DbContext such as Database are skipped
                foreach (var propertyInfo in _context.GetType().GetInstanceProperties()
                    .Where(p => p.GetIndexParameters().Length == 0
                        && p.DeclaringType != typeof(DbContext)))
                {
                    var entityType = GetSetType(propertyInfo.PropertyType);
                    if (entityType != null)
                    {
                        // We validate immediately because a DbSet/IDbSet must be of
                        // a valid entity type since otherwise you could never use an instance.
                        if (!entityType.IsValidStructuralType())
                        {
                            throw Error.InvalidEntityType(entityType);
                        }

                        List<string> properties;
                        if (!entityTypes.TryGetValue(entityType, out properties))
                        {
                            properties = new List<string>();
                            entityTypes[entityType] = properties;
                        }
                        properties.Add(propertyInfo.Name);

                        if (DbSetPropertyShouldBeInitialized(propertyInfo))
                        {
                            var setter = propertyInfo.Setter();
                            if (setter != null && setter.IsPublic)
                            {
                                var setMethod = SetMethod.MakeGenericMethod(entityType);

                                var newExpression = Expression.Call(dbContextParam, setMethod);
                                var setExpression = Expression.Call(
                                    Expression.Convert(dbContextParam, _context.GetType()), setter, newExpression);
                                initDelegates.Add(
                                    Expression.Lambda<Action<DbContext>>(setExpression, dbContextParam).Compile());
                            }
                        }
                    }
                }

                Action<DbContext> initializer = dbContext =>
                    {
                        foreach (var initer in initDelegates)
                        {
                            initer(dbContext);
                        }
                    };

                setsInfo = new DbContextTypesInitializersPair(entityTypes, initializer);

                // If TryAdd fails it just means some other thread got here first, which is okay
                // since the end result is the same info anyway.
                _objectSetInitializers.TryAdd(_context.GetType(), setsInfo);
            }
            return setsInfo.EntityTypeToPropertyNameMap;
        }