我正在使用DDD和NHibernate来保存我的域对象。在我的数据库中,与实体相关的每个表都有四个用于审计跟踪的额外列(CreatedBy,UpdatedBy,CreatedDate,UpdatedDate)。我使用的存储库模式只允许保存聚合根。当NHibernate尝试在聚合根上保存实体时,我得到一个SQL DateTime错误,因为实体没有设置其审计属性。 NHibernate中有没有办法在保存之前设置对象的属性?
这是一个小例子。我有一个Order对象,它是聚合根。我也有OrderNote对象,它们是订单的子项。当我向Order添加OrderNote然后保存Order时,抛出异常,因为CreatedDate / UpdatedDate设置为DateTime.MinValue,这将导致SQL DateTime溢出。由于这些审计列是持久性的一部分而与问题域无关,因此我不希望订单聚合根在添加注释时设置这些属性。审计列/属性只应由持久性框架而不是域知道。我希望能够告诉NHibernate在保存或更新时设置这些属性。有没有办法做到这一点?
答案 0 :(得分: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继承,如果您只需要覆盖某些方法,这会使事情变得更容易。
我从未使用过活动。
答案 1 :(得分:1)
您还可以查看NHibernate的版本控制系统,它可以为您提供帮助;)