Передача нескольких операторов включения в хранилище? - PullRequest
0 голосов
/ 26 августа 2011

Я пытаюсь найти способ передать коллекцию операторов include в мой репозиторий, чтобы я мог включить в нее конкретные объекты.Ниже приведен пример кода из моего репозитория.

   public TEntity GetById(Guid id)
        {
            return id != Guid.Empty ? GetSet().Find(id) : null;
        }
   private IDbSet<TEntity> GetSet()
            {
                return _unitOfWork.CreateSet<TEntity>();
            }

Метод GetByID вызывает GetSet для возврата набора сущностей.Я думал, если бы я мог как-то передать коллекцию сущностей для включения (через выражение) как часть моего GetById, таким образом, мне не пришлось бы выставлять GetSet для моих сервисов.Итак, что-то вроде этого:

var entity = _repository.GetById (theId, e => {e.Prop1, e.Prop2, e.Prop3});

Я мог бы затем передать этовыражение в мой метод GetSet и передать его в оператор включения.Мысли?

Ответы [ 4 ]

16 голосов
/ 26 августа 2011

Я недавно сделал что-то подобное в своем коде. Будет ли следующее работать для вас?

public TEntity GetById(Guid id, params Expression<Func<TEntity, object>>[] includeProperties)
    {
        if (id == Guid.Empty) return null;

        var set = _unitOfWork.CreateSet<TEntity>();
        foreach(var includeProperty in includeProperties)
        {
             set.Include(includeProperty);
        }
        return set.First(i => i.Id == id);
    }

Тогда вы бы назвали это так ...

var entity = _repository.GetById(theId, e => e.Prop1, e=> e.Prop2, e=> e.Prop3);

Я знаю, что это не совсем соответствует вашему образцу, но я думаю, что вы можете изменить его по необходимости.

8 голосов
/ 05 мая 2012

Я не думаю, что код Пейдж Кук будет работать так, как показано.

Я включил измененную версию кода, которая должна работать взамен:

public TEntity GetById(Guid id, params Expression<Func<TEntity, object>>[] includeProperties)
{
    if (id == Guid.Empty) return null;

    IQueryable<TEntity> set = _unitOfWork.CreateSet<TEntity>();

    foreach(var includeProperty in includeProperties)
    {
         set = set.Include(includeProperty);
    }
    return set.First(i => i.Id == id);
}

Я только заметил это, отследив SQL, сгенерированный Entity Framework, и понял, что оригинальный код был толькосоздавая иллюзию работы, используя ленивую загрузку для заполнения сущностей, указанных для включения.

Существует на самом деле более краткий синтаксис для применения операторов включения с использованием агрегатного метода LINQ , которыйв сообщении в блоге, связанном с.В моем посте также немного улучшен метод за счет возврата к методу Find, когда не требуется никаких включений, а также показан пример реализации метода «GetAll» с использованием аналогичного синтаксиса.

0 голосов
/ 14 января 2015

Плохая идея хранить контекст в нелокальном пространстве по многим причинам.

Я изменяю код Стива и получаю его для моих проектов ASP.NET MVC:

public aspnet_User FirstElement(Func<aspnet_User, bool> predicate = null, params Expression<Func<aspnet_User, object>>[] includes)
    {
        aspnet_User result;
        using (var context = new DataContext())
        {
            try
            {
                var set = context.Users.AsQueryable();

                for (int i = 0; i < includes.Count(); i++ )
                    set = set.Include(includes[i]);

                if (predicate != null)
                    result = set.ToList().FirstOrDefault(predicate);
                else
                    result = set.ToList().FirstOrDefault();
            }
            catch
            {
                result = null;
            }
        }

        return result;
    }
0 голосов
/ 26 августа 2011

Метод include можно объединить в вашем запросе linq следующим образом:

var result = (from i in dbContext.TableName.Include("RelationProperty")
                                           .Include("RelationProperty")
                                           .Include("RelationProperty")
                select i);
...