Я использую аналогичный подход в своей программе ASP.NET MVC, и пока он работает очень хорошо.
Мой IUnitOfWork
интерфейс выглядит так:
public interface IUnitOfWork
{
IRepository<TEntity> GetRepositoryFor<TEntity>() where TEntity : class;
void SaveChanges();
}
и связанный интерфейс IRepository
выглядит так:
public interface IRepository<TEntity> : IQueryable<TEntity> where TEntity : class
{
TEntity Find(params object[] keyValues);
void Insert(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
}
А затем передайте его моему сервису так:
public abstract class BaseService
{
public BaseService(IUnitOfWork unitOfWork)
{
// etc...
}
}
Вы правы в том, что это позволяет службе легко разрешать свои репозитории без необходимости передавать их в конструктор по отдельности, что полезно в случаях, когда вы можете работать с несколькими репозиториями в одной службе (например, заказы на покупку и продукты).
Одним из преимуществ использования таких интерфейсов, не зависящих от ORM, является то, что это означает, что вы можете легко переключаться между ORM. Я буду честен, шансы на то, что я перейду с Entity Framework на другую ORM, невелики, но факт в том, что я мог бы, если возникнет необходимость. В качестве бонуса мои сервисы намного проще тестировать, и я также считаю, что это делает мой класс сервиса чище, поскольку теперь он совершенно не знает об используемом ORM и работает полностью против двух интерфейсов выше.
Что касается комментариев об универсальном интерфейсе репозитория, мой совет — быть прагматичным и делать то, что лучше всего подходит для вас и вашего приложения. В Stackoverflow есть ряд вопросов по этой самой теме, и ответы на них сильно различаются в зависимости от того, какой путь лучше выбрать (например, разоблачение IQueryable
против IEnumerable
, общий против не общего).
Я играл с отсутствием универсального репозитория, поскольку вы, возможно, уже заметили, что мой интерфейс IRepository
выглядит как IDbSet
; Причина, по которой я выбрал этот метод, заключается в том, что он позволяет моей реализации обрабатывать все элементы управления состоянием сущностей Entity Framework, которые вы делаете с DbContext
E.G.
public void Delete(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
EntitySet.Attach(entity);
}
EntitySet.Remove(entity);
}
Если бы я использовал IDbSet
, мне нужно было бы выполнить это на моем сервисном уровне, что потребовало бы зависимости от DbContext
, которая казалась гораздо более дырявой абстракцией, чем мой общий репозиторий.
person
Benjamin Gale
schedule
24.04.2013