Включить нет - PullRequest
       35

Включить нет

1 голос
/ 22 апреля 2011

Я пытаюсь заменить объединения и использую 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 Ответ

2 голосов
/ 22 апреля 2011

Include загружается очень активно и заполняет свойства навигации в реальных объектах без необходимости проецирования на не тип объекта - этого нельзя достичь с помощью объединений.Также Include использует левые внешние объединения, тогда как ваш запрос использует внутренние объединения, поэтому вы не получите сущности, у которых нет связанных сущностей.

В EFv1 и EFv4 Include - это метод ObjectQuery.Я написал этот ответ , используя EFv4.1, который содержит метод расширения для IQueryable<T>, а также Includes с лямбда-выражением.Вы можете попробовать это - это просто еще одна библиотека, с которой вы будете ссылаться на свой проект, и вы все равно сможете использовать EFv4.

Причина переноса Включить в пользовательский метод - не вводить зависимость от 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 делает это внутренне) - этоможет стать серьезной проблемой в модульных тестах, когда вы не работаете с реальными запросами.

...