事务边界应该在存储库模式中的哪个位置?

时间:2010-01-11 22:37:51

标签: nhibernate transactions repository

我有一个像这样的存储库:

public interface IRepository
{
    void Save<T>(T entity);
    void Create<T>(T entity);
    void Update<T>(T entity);
    void Delete<T>(T entity);
    IQueryable<T> GetAll<T>();
}

我的问题是,我的交易边界应该在哪里?我应该在每个方法上打开一个新事务并在返回之前提交它吗?或者它应该在整个存储库周围,以便只在存储库被处理/垃圾收集时提交事务?

3 个答案:

答案 0 :(得分:3)

交易不应该应用于存储库,因为如果多个人需要参与交易,就无法说出来。

有一个单独的服务层,它使用存储库和模型对象来满足用例。服务方法知道事务边界需要在哪里。这就是他们应该应用的地方。

答案 1 :(得分:1)

工作单位绝对是最佳选择。如果您将SQL Server与本地数据库一起使用,TransactionScope将为您完成大部分繁重工作;只要你在存储库之间共享会话(你通过构造函数注入,正确......?),那么你可以将它们嵌入到你内心的内容中。默认情况下,如果有“环境”事务,它会在“环境”事务中登记,如果没有,则启动新事务,这正是您对工作单元所需的行为。

因此,您的存储库可能如下所示:

public class UserRepository : IUserRepository
{
    public UserRepository(ISession session)
    {
        this.Session = session;
    }

    public void Save(User user)
    {
        using (TransactionScope tsc = new TransactionScope())
        {
            Session.Save(user);
            tsc.Complete();
        }
    }

    protected ISession Session { get; set; }
}

public class OrderRepository : IOrderRepository
{
    public OrderRepository(ISession session)
    {
        this.Session = session;
    }

    public void Save(Order order)
    {
        using (TransactionScope tsc = new TransactionScope())
        {
            Session.Save(order);
            tsc.Complete();
        }
    }

    protected ISession Session { get; set; }
}

然后你可以像这样执行完整的工作单元:

User currentUser = GetCurrentUser();
using (TransactionScope tsc = new TransactionScope())
{
    ISession session = SessionFactory.OpenSession();

    Order order = new Order(...);
    order.User = currentUser;
    IOrderRepository orderRepository = GetOrderRepository(session);
    orderRepository.Save(order);

    currentUser.LastOrderDate = DateTime.Now;
    IUserRepository userRepository = GetUserRepository(session);
    userRepository.Save(currentUser);

    tsc.Complete();
}

如果你不喜欢TransactionScope或者你的环境阻止你有效地使用它,那么你总是可以实现自己的UOW或使用现有的实现。或者,如果你只是一个建筑整洁的怪物,那么你可以做两件事 - 使用一个主要DI库的通用工作单元接口,并使用TransactionScope实现你的具体UOW。

答案 2 :(得分:0)

其中一个选项是工作单元模式。以前的几个问题已经对此进行了解释。