Как стать автором
Обновить
22
0
Дмитрий Панюшкин @gnaeus

Пользователь

Отправить сообщение

Я тоже смотрел это видео перед написанием статьи =) На первый взгляд, там все правильно и красиво. Единственный вопрос — а зачем?


место хранения часто используемых запросов к сущности

А вот тут уже суровая реальность: Вы будете выносить запросы в репозиторий по мере рефакторинга. А Ваш коллега просто напихает от балды. Со временем все равно класс распухнет. Потому что его ответственность "часто используемые запросы" слишком размыта. Группировать запросы надо. Но по бизнес-кейсам, а не по сущностями.

Так я не говорю, что репозиторий зло. Репозиторий это отличная абстракция, и она у нас уже есть — IDbSet.

А вот от догмы, что все запросы к MyEntity должны лежать в MyEntityRepository нужно отступить.
Nullable?

Тогда уж лучше сразу


IEnumerable<Post> Filter(PostCriteria criteria);

class PostCriteria
{
    public int? AuthorId { get; set; }
    public DateTime? Date { get; set; }
    public string Tag { get; set; }
    // и т.п.
}

Но я про другое. Для extension-методов:


.FilterByDateAndTag(date, tag)
// эквивалентно
.FilterByDate(date).FilterByTag(tag)

И их можно использовать в подзапросах в в отличие от..


context.Users.Select(user => new
{
    User = user,
    Posts = user.Posts.FilterByDate(today).ToList(),
})
реализацию Repository специально для тестирования

Только вот замокать репозиторий с достаточно богатым API — та еще задачка. Лучше уж In-Memory Context. А вот IQueryable замокать элементарно — new List<T>().

Это Вы про extension-методы? Хороший вопрос на самом деле. Надо проверять.


Но, чисто умозрительно, кэширование должно работать. Магия не встраивается внутрь EF. Она работает как декоратор вокруг LINQ IQueryable. И тот Expression, который содержится во внутреннем IQueryable из EntityFramework, уже не содержит никакой магии. Ну и компиляция SQL происходит из нормального ExpressionTree.


В принципе, когда мы добавляем в цепочку вызовов еще один LINQ-метод:


query.Where(...).Select(...).OrderBy(...)

мы точно так же модифицируем IQueryable.Expression.

базовый класс для доменной сущности

Ну это как-то ортогонально созданию кастомного репозитория.


А вот насчет Repository и UnitOfWork — либо через год они превратятся в неподдерживаемое нечто (времени на рефакторинг не хватило). Либо со временем окажется, что Вы пишете на собственном фреймворке поверх EF (времени хватило).


А еще, такие репозитории — это пустая абстракиця. В них нет ни бизнес-логики, ни инфраструктурной логики. Это как адаптер. Только он используется не для интеграции двух разных модулей. А для интеграции EF и кода, который еще даже не написан.

Тут я пожалуй соглашусь. Мне самому комфортнее с extension-методами. Особенно, если дополнить их возможностью вызова из ExpressionTree, как описано в конце статьи.


Спецификации — это не способ облегчить жизнь разработчику, а скорее способ оформить все "по феншую" (DDD, TDD, переиспользование и т.п.).


И еще иногда (очень редко) возникает потребность динамически комбинировать условия с выборки помощью OR. Для AND все просто — добавляем в цепочку запроса несколько .Where()
А для OR или спецификация, или PredicateBuilder из LinqKit

Зато теперь можно тыкнуть их носом в эту статью =)

У меня за последние три года несколько раз случались холивары на эту тему с товарищами по команде.
Причем в разных конторах. Вот, решил оформить свои мысли в статью.
12 ...
11

Информация

В рейтинге
Не участвует
Откуда
Калуга, Калужская обл., Россия
Дата рождения
Зарегистрирован
Активность