这是一个围绕 DDD 进行存储库模式设计的良好工作单元吗?

发布于 2025-01-07 07:44:34 字数 2838 浏览 0 评论 0原文

我正在使用 UOW 和存储库模式构建一个 Web 应用程序。我对此有基本的了解,我想知道是否应该为项目中的所有表保留一个 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 在两个 Home 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
         }
   }

你觉得怎么样?如果这不是 DDD 的 UOW 和存储库模式的正确实现,它是否会因为编写一堆代码来抽象对 EF 表的调用而失败?

谢谢你的时间..

I am building a web app with using UOW and Repository pattern. I have a basic understanding of the same and I wanted to know if I should keep one UOW implementation for all the tables in my project or keep a separate one as per functionality like for eg:

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; }
}

As you can see TableA is available in both Home UOW as well as a particular business case UOW. One UOW partially implemented as below:

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;
        }
    }
 }

My repositories will be like so

    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
         }
   }

What do you think? If this is not the correct implementation of UOW and Repository pattern for DDD, will it fail as just a bunch of code written to abstract the call to the EF tables?

Thanks for your time..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坚持沉默 2025-01-14 07:44:34

我对通用存储库过敏。每次我使用它时,我都必须采取打破开放/封闭原则的变通办法。

我建议您切换到根聚合特定存储库并在其中使用您的 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 中获得事务支持的我最喜欢的解决方案是创建一个名为 TransactionalAttribute 的自定义 ActionFilter 并让它处理 UnitOfWork 实现:

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

我刚刚将答案转换为更详细的博客文章:http://blog.gauffin.org/2012/02/repositories-unit-of-work-and-asp-net-mvc/

I'm allergic to generic repositories. Each time I've used one I've had to do workarounds which breaks open/closed principle.

I recommend that you switch to root aggregate specific repositories and use your OR/M in them.

As for unit of work. EF and nhibernate do already implement the pattern. Simply create an interface like:

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

Disposing without saving = Rollback.

A nhibernate implementation would look like (quick writeup, not tested):

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

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

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

Using an IoC container makes it really easy. Just register the implementation in it.

My favorite solution to get transaction support in ASP.NET MVC is to create a custom ActionFilter named something like TransactionalAttribute and let it handle the UnitOfWork implementation:

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

I just converted the answer into a more detailed blog post: http://blog.gauffin.org/2012/02/repositories-unit-of-work-and-asp-net-mvc/

伤感在游骋 2025-01-14 07:44:34

我认为这是错误的。

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;
}

I think this is wrong.

UnitOfWork is Transaction (in simple words). It least it should contain one method Complete(Commit).

If you work with EntityFramework you wrap ObjectContext, if you work with pure ADO .NET you wrap TransactionScope, if with NHibernate ISession, etc.

Here is my UOF:

public interface IUnitOfWork : IDisposable
{
    void Complete();
    TRepository GetRepository<TRepository, TItem>()
        where TRepository : IRepository<TItem>
        where TItem : class;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文