Как лучше всего спроектировать generic репозиторий на базе EF Code First
От: DmytroL Украина http://www.linkedin.com/in/dmytrol
Дата: 03.06.14 08:28
Оценка: -1
Всем привет,

Поиском по форуму ответа не нашел, в Интернетах предлагают самые различные варианты решений, к сожалению, без анализа плюсов/минусов. Поэтому обращаюсь за советом к сообществу.

Итак, чего хочется:


  1. Абстрагировать Entity Framework от всего остального кода в виде интерфейсов Repository / Unit of Work (в далеком будущем не исключен вариант замены связки EF + SQL Server на, например, NoSQL хранилище, поэтому очень не хочется завязывать остальной код на специфичные для EF интерфейсы)
  2. Полная изоляция бизнес-логики в целях юнит-тестирования (т.е. создаем mock'и для IRepository / IUnitOfWork)
  3. Репозиторий не должен знать ничего о бизнес-логике (кол-во сущностей, специфические запросы для определенной сущности и т.п.), т.е. должен быть полностью обобщённым (generic)

Собственно, последний пункт вызывает больше всего вопросов, так как большинство примеров, которые я находил в Интернете, предлагают примерно такие варианты:


interface IUnitOfWork
{
  IRepository<Customer> Customers { get; }
  IRepository<Order> Orders { get; }
  // и т.п.
  void Commit();
}


а то и

interface IUnitOfWork
{
  ICustomerRepository Customers { get; }
  IOrderRepository Orders { get; }
  // и т.п.
  void Commit();
}


Которые плохи "протеканием" знаний о бизнес-сущностях в слой инфраструктуры. А вариант наподобие такого


interface IUnitOfWork
{
  IRepository<T> Repository { get; }
  void Commit();
}


встречается очень редко. А если и встречается, то в подобной реализации IUnitOfWork ручками кэшируются ссылки на DbSet<T> (хотя, вроде бы, DbContext сам должен это делать? )

Кроме этого, в примерах по Code First довольно часто создается класс-наследник DbContext, который, опять-таки, обладает знаниями о бизнес-логике:


public class MyDbContext: DbContext
{
  // ...
  public DbSet<Customer> Customers { get; }
  // ...
}


Это какое-то требование EF Code First — объявлять все возможные варианты параметризации DbSet как члены класса-наследника DbContext, или так делают просто для удобства, не задумываясь о low coupling и single responsibility principle ?

В общем, я немного запутался — наставьте, пожалуйста, на путь истинный!

Спасибо!
code first entity framework domain driven design oop
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.