我正在尝试测试一个简单的基于 NHibernate 的审计机制,该机制将每个更改的属性存储一行到更改日志表中。它实际上所做的是按预期执行实际的插入语句并执行两次审计日志记录。
所以,这就是我所做的:
string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=audittest;Integrated Security=SSPI;";
FluentConfiguration config = Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)).ShowSql())
.Mappings(x => x.FluentMappings.Add<Class1ClassMap>())
.Mappings(x => x.FluentMappings.Add<ChangeLogMap>())
.ExposeConfiguration(cfg =>
{
NHibernateAuditListener listener = new NHibernateAuditListener();
cfg.AppendListeners(ListenerType.PostInsert, new[] { listener });
});
ISessionFactory sf = config.BuildSessionFactory();
ISession session = sf.OpenSession();
using (ITransaction tr = session.BeginTransaction())
{
session.Save(new Class1()
{
FirstName="Peter",
LastName="Pan",
Id=100
});
tr.Commit();
}
编辑:
将日志记录代码更改为简单的代码以查看失败:
public void OnPostInsert(PostInsertEvent @event)
{
if (@event.Entity is IAuditable)
{
Console.WriteLine("----write audit----");
for (int index = 0; index < @event.State.Length; index++)
Console.WriteLine("----store changes of property {0}----",
@event.Persister.PropertyNames[index]);
}
}
这会生成以下输出:
NHibernate: INSERT INTO "Class1" (FirstName, LastName, Id) VALUES (@p0, @p1, @p2); @p0 = 'Peter' [Type: String (0)], @p1 = 'Pan' [Type: String (0)], @p2 = 1 [Type: Int64 (0)]
----write audit----
----store changes of property FirstName----
----store changes of property LastName----
----write audit----
----store changes of property FirstName----
----store changes of property LastName----
如您所见,错误的不是 EventHandler 代码,而是调用它的框架行为异常(调用 OnPostInsert 方法两次)。知道为什么会这样吗?
最佳答案
好的大家,问题存在于程序内部的处理细节上。您正在构建一个 FluentConfiguration 实例,它可以动态创建基本的 NHibernate 配置。
这是在调用这两行时完成的(变量配置是 FluentConfiguration
类型):
new SchemaExport(config.BuildConfiguration()).Create(true, true);
和
ISessionFactory sf = config.BuildSessionFactory();
FluentConfiguration 缓存第一个创建的实例并重新使用它为 ISessionFactory
实例创建新实例。在这两个调用中,FluentConfiguration
实例的 ExposeConfiguration
被调用。因此,在持久化数据的 session 中有 2 个 NHibernateAuditListener
实例。
像这样尝试:
string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=audittest;Integrated Security=SSPI;";
var config = Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)).ShowSql())
.Mappings(x => x.FluentMappings.Add<Class1ClassMap>())
.Mappings(x => x.FluentMappings.Add<ChangeLogMap>())
.ExposeConfiguration(cfg =>
{
NHibernateAuditListener listener = new NHibernateAuditListener();
cfg.AppendListeners(ListenerType.PostInsert, new[] { listener });
})
.BuildConfiguration();
new SchemaExport(config).Create(true, true);
Console.WriteLine("----------------------------------------------");
ISessionFactory sf = config.BuildSessionFactory();
ISession session = sf.OpenSession();
using (ITransaction tr = session.BeginTransaction())
{
session.Save(new Class1()
{
FirstName="Peter",
LastName="Pan",
Id=100
});
tr.Commit();
}
在 config
中,您现在拥有真正的 NHibernate Configuration 实例,只注册了一个 Listener。
明白了吗?!
关于events - NHibernate IPostInsertEventListener : Insert executed multiple times,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16395956/