2013-05-06 60 views
1

我想测试一个简单的基于NHibernate的审计机制,每个更改的属性存储一行到更改日志表。它实际上做的是按预期执行实际的插入语句并执行两次审计日志记录。NHibernate IPostInsertEventListener:插入多次执行

所以,这是我做的:

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

回答

2

好了大家,在的PROGRAMM内处理的细节中存在的问题。您正在建立一个FluentConfiguration实例,它实时创建基本的NHibernate配置。

这是对这些2行的呼叫完成(可变的配置是FluentConfiguration类型):

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

ISessionFactory sf = config.BuildSessionFactory(); 

的FluentConfiguration缓存所述第一创建的实例和再次用于创建ISessionFactory -instance的新实例。在两个调用中调用FluentConfiguration实例的ExposeConfiguration。所以会话中有两个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的配置实例有,只有一个监听器注册。

明白了吗?

+0

谢谢,MacX。再一次,你拯救了我自己造成的痛苦! – 2013-05-13 21:23:13