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

时间:2011-04-07 11:59:13

标签: repository layer unit-of-work isession

使用工作单元/存储库模式构建了一个小应用程序,我很难理解如何在我的业务层中正确使用它。我的应用程序有一个数据访问层,可以是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方法的开头重新打开相同的工作单元。

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

2 个答案:

答案 0 :(得分: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作为我们的存储库/ unitofwork模式,而不必将UoW传递到存储库。

答案 1 :(得分:0)

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

您的IUnitOfWork将被注入您的表示层,如mvc controller。

您的IUnitOfWork被注入mvc控制器。

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