1

我正在尝试测试一个简单的基于 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 方法)。任何想法为什么会发生这种情况?

示例项目下载

4

1 回答 1

2

好的大家,问题存在于程序内部处理的细节上。您正在构建一个 FluentConfiguration-instance,它会动态创建基本的 NHibernate 配置。

这是在调用这 2 行时完成的(变量 config 的类型为FluentConfiguration):

new SchemaExport(config.BuildConfiguration()).Create(true, true);

ISessionFactory sf = config.BuildSessionFactory(); 

FluentConfiguration 缓存第一个创建的实例并重用它来为ISessionFactory-instance 创建新实例。在这两个调用中ExposeConfigurationFluentConfiguration实例都被调用。NHibernateAuditListener因此,会话中有 2 个实例正在持久化数据。

试试这样:

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();
}    

您现在拥有真正的NHibernateconfig配置实例,只注册了一个侦听器。

知道了?!

于 2013-05-13T19:47:41.880 回答