Это хороший UnitOfWork с репозиторием Шаблон дизайна вокруг DDD - PullRequest
1 голос
/ 17 февраля 2012

Я создаю веб-приложение с использованием шаблона UOW и репозитория. У меня есть базовое понимание того же, и я хотел знать, должен ли я оставить одну реализацию UOW для всех таблиц в моем проекте или оставить отдельную в соответствии с функциональностью, например, для:

public interface IHomeUOW
{
    IGenericRepository<User> Users { get; }
    IGenericRepository<TableA> Table_A { get; }
    IGenericRepository<TableB> Table_B{ get; }
}

public interface IBusinessCaseUOW
{

    IGenericRepository<TableA> Table_A { get; }
    IGenericRepository<TableXYZ> Table_XYZ{ get; }
}

Как вы можете видеть, TableA доступна как в UOW для дома, так и в UOW для конкретного бизнеса. Одно UOW частично реализовано, как показано ниже:

public class UnitOfWork : IUnitOfWork
{

    private readonly ObjectContext _context;
    private UserRepository _userRepository;


    public UnitOfWork(ObjectContext Context)
    {

        if (Context == null)
        {
            throw new ArgumentNullException("Context wasn't supplied");
        }
        _context = Context;
    }

    public IGenericRepository<User> Users
    {
        get
        {
            if (_userRepository == null)
            {
                _userRepository = new UserRepository(_context);
            }

            return _userRepository;
        }
    }
 }

Мои репозитории будут такими же

    public interface IGenericRepository<T>
    where T : class
    {
        //Fetch records
        T GetSingleByRowIdentifier(int id);             
        T GetSingleByRowIdentifier(string id);          

        IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter);  

        // CRUD Ops
        void AddRow(T entity);
        void UpdateRow(T entity);
        void DeleteRow(T entity);

    }


    public abstract class GenericRepository<T> : IGenericRepository<T>
            where T : class
    {
        protected IObjectSet<T> _objectSet;
        protected ObjectContext _context;

        public GenericRepository(ObjectContext Context)
        {
            _objectSet = Context.CreateObjectSet<T>();
            _context = Context;
        }

        //Fetch Data
        public abstract T GetSingleByRowIdentifier(int id);
        public abstract T GetSingleByRowIdentifier(string id);


        public IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter)
        {
            //
        }

        //CRUD Operations implemented

    }

   public class UserRepository : GenericRepository<User>
   {
         public UserRepository(ObjectContext Context)
         : base(Context)
         {
         }

         public override User GetSingleByRowIdentifier(int id)
         {
          //implementation
         }

         public override User GetSingleByRowIdentifier(string username)
         {
          //implementation
         }
   }

Что ты думаешь? Если это не правильная реализация UOW и шаблона репозитория для DDD, он потерпит неудачу как просто набор кода, написанный для абстрагирования вызова таблиц EF?

Спасибо за ваше время ..

Ответы [ 2 ]

5 голосов
/ 17 февраля 2012

У меня аллергия на общие репозитории.Каждый раз, когда я использовал один, мне приходилось делать обходные пути, которые нарушали принцип открытия / закрытия.

Я рекомендую вам перейти к репозиториям, специфичным для корневых агрегатов, и использовать в них свой OR / M.

Что касается единицы работы.EF и nhibernate уже реализуют шаблон.Просто создайте интерфейс, например:

public interface IUnitOfWork : IDisposable
{
    void SaveChanges();
}

Утилизация без сохранения = Откат.

Реализация nhibernate будет выглядеть (быстрая запись, не тестировалась):

public class NHibernateUnitOfWork : IDisposable
{
    public NHibernateUnitOfWork(ISession session)
    {
        _transaction = session.BeginTransaction();
    }

    public void SaveChanges()
    {
        _transaction.Commit();
    }

    public void Dispose()
    { 
        _transaction.Dispose();
    }
}

Использование контейнера IoC делает его действительно простым.Просто зарегистрируйте в нем реализацию.

Мое любимое решение для получения поддержки транзакций в ASP.NET MVC - это создание пользовательского ActionFilter с именем, похожего на TransactionalAttribute, и разрешение на его реализацию UnitOfWork:

[HttpPost, Transactional]
public ActionResult Update(YourModel model)
{
}

Я только что преобразовал ответ в более подробное сообщение в блоге: http://blog.gauffin.org/2012/02/repositories-unit-of-work-and-asp-net-mvc/

1 голос
/ 17 февраля 2012

Я думаю, что это неправильно.

UnitOfWork - это транзакция (простыми словами).По крайней мере, он должен содержать один метод Complete (Commit).

Если вы работаете с EntityFramework, вы оборачиваете ObjectContext, если вы работаете с чистым ADO .NET, вы оборачиваете TransactionScope, если с NHibernate ISession и т. Д.

Вот мой UOF:

public interface IUnitOfWork : IDisposable
{
    void Complete();
    TRepository GetRepository<TRepository, TItem>()
        where TRepository : IRepository<TItem>
        where TItem : class;
}
...