NHibernate ITransaction和纯域模型

时间:2009-09-02 16:26:38

标签: nhibernate transactions persistence-ignorance

我正在尝试将域模型编写为尽可能持久性无知。我现在唯一要做的就是标记每个属性和方法virtual,因为NHibernate要求延迟加载。

在我的域模型程序集中,我定义了一些存储库接口:

public interface IRepository<TEntity> where TEntity : EntityBase {
    TEntity Get(int id);
    /* ... */
}
public interface IProductRepository : IRepository<Product> { ... }

然后我有数据汇编。这个将引用NHibernate,它知道它的存在。这是实现这些存储库接口的程序集:

public abstract class Repository<TEntity> : IRepository<TEntity> {
    public TEntity Get(ind id) { ... }
    /* ... */
}
public class ProductRepository : Repository<Product>, IProductRepository {
    /* ... */
}

等等。

现在我想实现交易功能到我的存储库。为此,我将在我的IRepository接口上添加BeginTransaction方法。但是,我无法将其返回类型定义为NHibernate.ITransaction,因为我想保持域模型持久性无知,而不是被迫从我的域模型程序集引用NHibernate的程序集。

你会做什么?

您是否只需在界面上实施void BeginTransaction()void Commit()void RollBack()方法,然后让存储库实施在内部管理ITransaction对象

或者你会找到一种方法公开ITransaction对象让客户端直接使用它来管理事务,而不是使用存储库的方法吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

您可以查看已经实现了所有内容的Sharp Architecture,包括具有事务支持的通用存储库。解决方案是IRepository具有封装事务的DbContext属性(它实际上是一个接口)。 这是您描述的第一个选项(隐藏NHibernate的自定义事务接口)。它运作良好。

我想你甚至可以重复使用S#arp代码,无论你是否打算使用完整的框架。

答案 1 :(得分:0)

IMO事务总是应该以业务逻辑开始和结束,换句话说,事务应该从服务层而不是存储库层开始,并且存储库应该在事务中登记它自己,理想情况下这将是隐式完成的。

现在如果您正在使用NH,那么如果您的服务和存储库共享相同的“会话”(他们应该),那么您可以在服务层中调用“BeginTransaction”并根据需要提交或回滚:

例如,想象一下服务上的这个方法:

  public void RegisterCustomer(Customer customer)
    {
        try
        {
            using(var transaction = _session.BeginTransaction())
            {
                _customerRepository.Save(customer);
                _customerSurveyRepository.Save(customerSurvey);
                // DO What ever else you want...
                transaction.Commit();
            }
        }
        catch (Exception exn)
        {
            throw new AMException(FAILED_REGISTRATION, exn);
        }
     }

如何通过注入构造函数或使用SessionFactory获取当前会话来解决存储库如何获取对同一Session的引用...