2009-07-20 68 views
11

我使用DDD和NHibernate来坚持我的域对象。在我的数据库中,与实体相关的每个表都有四个用于审计跟踪的额外列(CreatedBy,UpdatedBy,CreatedDate,UpdatedDate)。我正在使用仅允许保存聚合根的存储库模式。当NHibernate试图保存聚合根上的实体时,我得到一个SQL DateTime错误,因为这些实体没有设置它们的审计属性。 NHibernate中有一种方法可以在保存之前设置对象的属性吗?NHibernate自动设置属性保存

这是一个小例子。我有一个Order对象,它是聚合根。我也有订单子项目的OrderNote对象。当我将OrderNote添加到Order并保存Order时,会抛出一个异常,因为将CreatedDate/UpdatedDate设置为DateTime.MinValue会导致SQL DateTime溢出。由于这些审计列是持久性的一部分,并且与问题域无关,因此我不希望订单聚合根在添加注释时设置这些属性。审计列/属性只应由持久性框架而不是域来知晓。我希望能够告诉NHibernate在保存或更新时设置这些属性。有没有办法做到这一点?

回答

11

拦截器可以做到这一点:

http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-interceptors(9.10,链接并不总是有效)。

剪切/膏从文档:

public class AuditInterceptor : IInterceptor 
{ 
    ... 

    public boolean OnSave(object entity, 
          object id, 
          object[] state, 
          string[] propertyNames, 
          IType[] types) 
    { 
     if (entity is IAuditable) 
     { 
      for (int i=0; i<propertyNames.Length; i++) 
      { 
       if ("CreateTimestamp" == propertyNames[i]) 
       { 
        state[i] = DateTime.Now; 
        return true; 
       } 
      } 
     } 
     return false; 
    } 

} 

OnFlushDirty()可用于UpdatedDate。

您将希望每个拥有CreatedDate/UpdatedDate的实体都实现一个接口,以便拦截器可以检查它是否应该起作用(在提供的示例中,它是IAuditable)。


编辑

只注意到第11章:拦截器和事件。您可以从EmptyInterceptor继承,如果您只需要重写某些方法,就可以使事情变得更轻松。

我从来没有使用过活动。

+0

很好。这正是我要找的。我是NHibernate的新手,并没有意识到这个功能。我确实有一个用受保护属性实现的IAuditable接口,因此域无法看到它们。 – awilinsk 2009-07-20 14:54:35

1

你也可以看看NHibernate的版本控制系统,它可以帮助你的情况;)