【问题标题】:Include is gone包括消失了
【发布时间】:2011-04-21 20:42:02
【问题描述】:

我正在尝试替换连接并使用包含,但我不知道该怎么做:

          IRepository<Call> callRepository =
            ObjectFactory.GetInstance<IRepository<Call>>();

        IRepository<Reason> reasonRepository =
            ObjectFactory.GetInstance<IRepository<Reason>>();

        IRepository<SimTask.Domain.Business.Entities.System.Company>
            companyRepository = ObjectFactory.GetInstance<IRepository<SimTask.Domain.
            Business.Entities.System.Company>>();

        IQueryable<CallsListItem> x =
            from call in callRepository.GetQuery()
            join reason in reasonRepository.GetQuery() on call.ReasonId equals reason.Id
            join company in companyRepository.GetQuery() on call.CompanyId equals company.CompanyId
            where call.CompanyId == companyId &&
                (!isClosed.HasValue || call.IsClosed.Equals(isClosed.Value))
            select new CallsListItem()
            {
                CallId = call.Id,
                Description = call.Description,
                CloseDateTime = call.CloseDateTime,
                IsClosed = call.IsClosed,
                OpenDateTime = call.OpenDateTime,
                PhoneNumber = call.PhoneNumber,
                ReasonName = reason.Name,
                CompanyName = company.CompanyName
            };

IRepository 由以下人员实现:

public class EFRepository<T> : IRepository<T> where T : class
    {
        ObjectContext _context;
        IObjectSet<T> _objectSet;

        private ObjectContext Context
        {
            get
            {
                if (_context == null)
                {
                    _context = GetCurrentUnitOfWork<EFUnitOfWork>().Context;
                }
                return _context;
            }
        }

        private IObjectSet<T> ObjectSet
        {
            get
            {
                if (_objectSet == null)
                {
                    _objectSet = this.Context.CreateObjectSet<T>();
                }
                return _objectSet;
            }
        }

        public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>() where TUnitOfWork : IUnitOfWork
        {
            return (TUnitOfWork)UnitOfWork.Current;
        }

        public IQueryable<T> GetQuery()
        {
            return ObjectSet;
        }

        public IEnumerable<T> GetAll()
        {
            return GetQuery().ToList();
        }

        public IEnumerable<T> Find(Func<T,bool> where)
        {
            return this.ObjectSet.Where<T>(where);
        }

        public T  Single(Func<T,bool> where)
        {
            return this.ObjectSet.Single<T>(where);
        }

        public T First(Func<T,bool> where)
        {
            return this.ObjectSet.First<T>(where);
        }

        public void Delete(T entity)
        {
            this.ObjectSet.DeleteObject(entity);
        }

        public void Add(T entity)
        {
            this.ObjectSet.AddObject(entity);
        }

        public void Attach(T entity)
        {
            this.ObjectSet.Attach(entity);
        }

        public void SaveChanges()
        {
            this.Context.SaveChanges();
        }
    }

为什么包含比连接更好?
如何包含?

【问题讨论】:

    标签: c# .net entity-framework linq-to-entities iqueryable


    【解决方案1】:

    Include 是即时加载,它填充真实实体中的导航属性,而无需投影到非实体类型 - 这无法通过连接来实现。此外,Include 使用左外连接,而您的查询使用内连接,因此您不会获得没有相关实体的实体。

    在 EFv1 和 EFv4 中,IncludeObjectQuery 的方法。我使用 EFv4.1 编写了 this answer,其中包含 IQueryable&lt;T&gt; 的扩展方法以及带有 lambda 表达式的 Includes。您可以try it - 它只是您将链接到您的项目的另一个库,您仍然可以使用 EFv4。

    在自定义方法中包装 Include 的原因是没有在上层引入对 EF 的依赖。如果你不下载 EFv4.1,你可以使用这个:

    public static IQueryable<T> IncludeMultiple<T>(this IQueryable<T> query, params string[] includes)
        where T : class
    {
        if (includes != null)
        {
            var objectQuery = query as ObjectQuery;
    
            if (objectQuery == null)
            {
                throw new InvalidOperationException("...");
            }
    
            objectQuery = includes.Aggregate(objectQuery, 
                      (current, include) => current.Include(include));
        }
    
        return objectQuery;
    }
    

    这两种方法(EFv4 和 EFv4.1)的最大缺点是转换为 ObjectQuery(EFv4.1 在内部执行) - 这在您不使用实际查询的单元测试中可能是一个严重的问题。

    【讨论】:

    • 嗨,我不明白这一点:“在自定义方法中包装 Include 的原因是没有在上层引入对 EF 的依赖”。通过使用它,我强制使用 EF4.1。此外 - 我把这个扩展放在我的解决方案的数据层..
    • 是的,但是如果想在数据层中隐藏所有与 EF 相关的代码,您不想将 Include 从实体框架公开到上层,因为您可以将其包装到数据中的自定义方法中层。
    • 哇..这导致了其他问题..我在我的业务层中进行与业务实体相关的查询,所以我需要这个包括..此外,为了初始化我的应用程序 - 表示层应该知道数据层(global.asax中有StructureMap的ObjectFactory的初始化)
    • @Naor:是的,如果从代码中引导 StructureMap,则需要对 EF 的依赖。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多