2013-05-06 57 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