events - NHibernate IPostInsertEventListener : Insert executed multiple times

标签 events nhibernate testing triggers fluent-nhibernate

我正在尝试测试一个简单的基于 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 方法两次)。知道为什么会这样吗?

SAMPLE PROJECT DOWNLOAD

最佳答案

好的大家,问题存在于程序内部的处理细节上。您正在构建一个 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/

相关文章:

swift - XCUITest中是否可以直接开屏?

testing - 如何使带有@BeforeClass 的方法运行多次?

c# - CheckedChanged 事件中的问题

javascript - 如何使用 knockout.js 获取文本框 onchange 的值

javascript - Internet Explorer 和 JavaScript 事件 currentTarget

c# - 在 Fluent NHibernate 中,如何将自动映射类型与非自动映射类型结合起来?

events - ZF3 - 附加到 EventManager 的事件未触发

NHibernate 和 Spring.NET 的结合在企业级应用中真的很有帮助!

NHibernate 在断开连接的情况下

testing - 在每个浏览器的钩子(Hook)之前运行