包括已经消失了

时间:2011-04-21 20:42:03

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

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

          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();
        }
    }

为什么包括更好然后加入?
我该怎么办?

1 个答案:

答案 0 :(得分:2)

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

在EFv1和EFv4中,IncludeObjectQuery的方法。我使用EFv4.1编写了this answer,其中包含IQueryable<T>的扩展方法以及带有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在内部执行) - 在单元测试中,这可能是一个严重的问题,您无法使用真正的查询。