为什么不急于在Entity Framework中加载

时间:2016-06-16 15:49:21

标签: entity-framework eager-loading

我正在尝试在ProjectVersions列表上进行基本的预先加载,其中每个ProjectVersion都有一个FieldValues和ChildProjects列表。我希望在加载ProjectVersions时将FieldValues和ChildProjects及其所有属性一起加载,但似乎在我的代码中,当经历每个ProjectVersion时,它仍然会访问数据库以获取这些集合(检查sql server profiler)。任何指针都会有所帮助。

    var publishedList = Repository.Find<Project>().//a bunch of wheres and selects

            IEnumerable<ProjectVersion> publishedList = published
                .Include(x => x.FieldValues)
                .Include(x => x.ChildProjects)
                .ToList();

    //EDIT: the context is hidden behind a generic Repository. Below are some details:

        public class Repository : IRepository
            {
                internal readonly IDataContext _context;

                public Repository(IDataContext context)
                {
                    _context = context;
                    _context.Committed += _context_Committed;
                    _context.Deleted += _context_Deleted;
                }
                public IQueryable<T> Find<T>() where T : class, IEntity
                {
                    return _context.Repository<T>();
                }
        }

        public class EfDataContext : IDataContext
            {
                public IQueryable<T> Repository<T>() where T : class, IEntity
                {
                    var table = _context.Set(typeof(T));
                    WrappedFieldsObjectQuery<T>(table.Cast<T>().AsExpandable()));
                    return table.Cast<T>().AsExpandable();
                }
        }

    public class MsmDbContext : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
                .Where(type =>
                    type.IsClass &&
                    type.BaseType.IsGenericType &&
                    type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));

            foreach (var config in typesToRegister.Select(Activator.CreateInstance))
            {
                modelBuilder.Configurations.Add((dynamic)config);
            }

            base.OnModelCreating(modelBuilder);
        }
    }

    public class ProjectMapping : EntityTypeConfiguration<Project>
    {
        public ProjectMapping()
        {
            HasOptional(p => p.LastChangedBy).WithMany(p => p.ProjectsChanged).WillCascadeOnDelete();
            HasRequired(p => p.CreatedBy).WithMany(p => p.ProjectsCreated).WillCascadeOnDelete();
            HasRequired(d => d.Account).WithMany(p => p.Projects).WillCascadeOnDelete();
            HasRequired(d => d.PinType).WithMany(p => p.Projects).HasForeignKey(p => p.PinType_Id).WillCascadeOnDelete();
        }
    }

    public static class RepositoryFactory
        {
            public static IRepository CreateRepository()
            {
                return CreateEfRepository();
            }

            internal static IRepository CreateEfRepository()
            {
                return new Repository(new EfDataContext(new MsmDbContext()));
            }
        }

2 个答案:

答案 0 :(得分:0)

好的,我看不到您的完整查询,但在您的评论中,您写了一些关于select的内容。一旦使用Include()进行自定义投影,EF就会忽略Select()语句,我猜这就是为什么急切加载不起作用的原因。而不是Include(),尝试将要加载的属性添加到投影中,例如

Repository.Find<Project>()
.Select(p => new { project = p, p.FieldValues, p.ChildProjects })
.AsEnumerable().Select(p => p.project).ToList()

这种投影将负责加载您的数据,您不需要Include()

答案 1 :(得分:0)

实际上,我通过直接使用DataContext来实现它。不知何故,存储库正在搞砸它。