包含消失了

发布于 2024-11-02 22:15:48 字数 3419 浏览 1 评论 0原文

我正在尝试替换联接并使用 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();
        }
    }

为什么 Include 比联接更好?
我怎样才能做到包含?

I am trying to replace the joins and use include but I don't know how to do that:

          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 is implemented by:

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

Why is Include better then joins?
How can I do Include?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

落日海湾 2024-11-09 22:15:48

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

在 EFv1 和 EFv4 中,IncludeObjectQuery 的一种方法。我使用 EFv4.1 编写了 这个答案,其中包含IQueryable 的扩展方法以及带有 lambda 表达式的 Includes。您可以尝试一下 - 它只是您将链接到项目的另一个库,您仍然可以使用 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 is eager loading and it fills navigation properties in real entities without need to project to non entity type - this cannot be achieved with joins. Also Include uses left outer joins whereas your query uses inner joins so you will not get entities which don't have related entity.

In EFv1 and EFv4 Include is a method of ObjectQuery. I wrote this answer using EFv4.1 which contains extension method for IQueryable<T> as well as Includes with lambda expression. You can try it - it is just another library you will link to your project and you can still use EFv4.

The reason to wrap Include in custom method is not introducing dependency to EF in upper layer. If you don't download EFv4.1 you can use this:

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

The big disadvantage in both approaches (EFv4 and EFv4.1) is casting to ObjectQuery (EFv4.1 do it internally) - this can be serious issue in unit tests where you don't work with real queries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文