2009-09-02 57 views
3

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

在我域模型组件我定义了一些库接口:

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

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

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

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来获取当前要解决会议...