3

我正在尝试将我的域模型尽可能地写成持久性无知。我现在唯一要做的就是标记每个属性和方法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 {
    /* ... */
}

等等。

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

你会怎么办?

您是否会简单地在接口上实现 a void BeginTransaction()、 avoid Commit()和 avoid RollBack()方法,并让存储库实现在ITransaction内部管理对象

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

谢谢!

4

2 回答 2

2

You can take a look at the Sharp Architecture which has already implemented everything you talk about, including generic repositories with transactions support. The solution there is that IRepository has DbContext property which encapsulates transactions (it's actually an interface). This is the first of the options that you described (custom transactions interface which hides NHibernate). And it works well.

I guess you can even re-use S#arp code regardless if you intend to use the full framework.

于 2009-09-04T18:34:52.880 回答
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);
        }
     }

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

于 2009-09-03T13:57:01.237 回答