【问题标题】:What is the correct way to use Unit of Work/Repositories within the business layer?在业务层中使用工作单元/存储库的正确方法是什么?
【发布时间】:2011-07-31 15:22:08
【问题描述】:

使用工作单元/存储库模式构建了一个小型应用程序后,我很难理解如何在我的业务层中正确使用它。我的应用程序有一个数据访问层,可以是 NHibernate 或实体框架。我可以轻松地在这些之间切换。

我有许多存储库,例如 Customer、Order 等。我的工作单元将是 ISession 或 Object Context,具体取决于我要测试的 DAL。

我的业务层包含一个业务方法 - CreateOrder()。我正在努力理解的是我应该在业务层的哪个位置初始化我的工作单元和我的存储库。

专注于 Nhibernate,我的 DAL 看起来像:

public class NHibernateDAL : IUnitOfWork
{
    log4net.ILog log = log4net.LogManager.GetLogger(typeof(NHibernateDAL));
    ISession context;

    public NHibernateDAL()
    {            
        context = SessionProvider.OpenSession();
        this.Context.BeginTransaction();
        CurrentSessionContext.Bind(context);            
    }

    public ISession Context
    {
        get { return context; }
    }

    public void Commit()
    {           
        this.Context.Transaction.Commit();
        context.Close();            
    }

    public void Dispose()
    {
        ISession session = CurrentSessionContext.Unbind(SessionProvider.SessionFactory);
        session.Close();
    }
}

在我的业务层中,我想知道我应该在哪里声明我的工作单元和存储库。它们是在类级别还是在 CreateOrder 方法中声明的?

例如:

public class BusinessLogic
{         
    UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
    NhRepository<Order> _orderRepository = new NhRepository<Order>(_unitOfWork);    
    NhRepository<Customer> _customerRepository = new NhRepository<Customer>(_unitOfWork);
    ....

    public void CreateOrder(.....)
    {
         Order order = new Order();
         _orderRepository.Add(order);

         _unitOfWork.Commit();
     }
}

以上代码仅适用于第一次调用 CreateOrder() 方法,但不适用于后续调用,因为会话已关闭。我尝试在提交事务后删除“context.Close()”调用,但这也失败了。尽管上述方法不起作用,但对我来说,在此范围内声明我的存储库和工作单元似乎更正确。

但是,如果我按照下面的方式实现它,它可以正常工作,但是在方法本身的范围内声明存储库和工作单元似乎是不自然的。如果我有大量的业务方法,那么我会在各处声明存储库和工作单元:

public class BusinessLogic
{                      
    public void CreateOrder(.....)
    {
         UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
         var _orderRepository = new NhRepository<Order>(_unitOfWork);    

         NhRepository<Customer> _customerRepository = null;
         Order order = new Order();
         _orderRepository.Add(order);             

         _unitOfWork.Commit();
     }
}

如果我要使用类级别声明来实现这一点,那么我认为我需要一些方法来在 CreateOrder 方法的开头重新打开相同的工作单元。

在业务层中使用工作单元和存储库的正确方法是什么?

【问题讨论】:

    标签: repository layer unit-of-work isession


    【解决方案1】:

    在我看来,您几乎掌握了它。在我们的新服务器堆栈中,我有这样的设置:

    WCF Service Layer  --> just returns results from my Business Layer
    
    My business layer is called, creates a unitofwork, creates the respository
    Calls the respository function
    Uses AutoMapper to move returned results into a DTO
    
    My repository gets the query results and populates a composite object.
    

    看起来几乎就像你在那里得到的一样。尽管我们使用 Unity 来定位您所说的业务层。 (我们称之为函数处理器)

    不过,我强烈建议您不要将 UnitOfWork 保留在班级级别。毕竟每个descreet函数都是一个工作单元。所以我的是这样的(为了保护无辜,改了名字):

            using ( UnitOfWorkScope scope = new UnitOfWorkScope( TransactionMode.Default ) )
            {
                ProcessRepository repository = new ProcessRepository(  );
                CompositionResultSet result = repository.Get( key );
                scope.Commit( );
    
                MapData( );
                return AutoMapper.Mapper.Map<ProcessSetDTO>( result );
            }
    

    我们还就何时执行 scope.Commit 进行了长时间的讨论,虽然查询不需要它,但它为应用层中的每个函数建立了一致的模式。顺便说一句,我们将 NCommon 用于我们的存储库/工作单元模式,并且不必将 UoW 传递给存储库。

    【讨论】:

      【解决方案2】:

      您的 IUnitOfWork 实现包含所有存储库。

      您的 IUnitOfWork 像 mvc 控制器一样被注入到您的表示层中。

      你的 IUnitOfWork 被注入到 mvc 控制器中。

      您的 IRepository 被注入到您的 UnitOfWork 实现中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-20
        • 1970-01-01
        • 2013-02-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-23
        • 1970-01-01
        • 2015-03-20
        相关资源
        最近更新 更多