2012-11-04 103 views
2

我使用nHibernate每個方法一個會話。我使用Castle Dynamic Proxy在執行方法之前打開一個會話和一個事務,並在執行此方法後立即提交事務並關閉會話。nHibernate與SQLite數據庫非常慢的更新

我正在使用SQLite數據庫,如果設置級聯到SaveUpdate或None不會更改任何內容。 nHIbernate用Fluent nHibernate配置爲默認配置。

當我刷新會話時,需要超過2秒。

public void AddNewChild(LightPatientDto patient, LightPatientDto child) 
{ 
    var ePatient = this.Session.Load<Patient>(patient.Id); 
    var eChild = this.Session.Load<Patient>(child.Id); 

    switch (ePatient.Gender) 
    { 
     case Gender.Male: 
      eChild.Father = ePatient; 
      break; 
     case Gender.Female: 
      eChild.Mother = ePatient; 
      break; 
     default: 
      Assert.FailOnEnumeration(eChild.Gender); 
      break; 
    } 

    this.Session.Update(eChild); 
    this.Session.Flush(); // <== takes more than 2 seconds 
} 

NHibernate profiler給我這個SQL在2008 ms執行。當我使用SQLite管理工具複製粘貼這個SQL時,它在90毫秒內執行。

UPDATE Patient 
SET BirthDate = '1964-05-06T00:00:00.00' /* @p0 */, 
     Fee = 0 /* @p1 */, 
     Height = 0 /* @p2 */, 
     InscriptionDate = '2007-05-21T00:00:00.00' /* @p3 */, 
     PlaceOfBirth = 'xxxxxx' /* @p4 */, 
     PrivateMail = '' /* @p5 */, 
     PrivateMobile = NULL /* @p6 */, 
     PrivatePhone = '0496/xx.xx.xx' /* @p7 */, 
     Reason = 'diabète' /* @p8 */, 
     Father_id = 2 /* @p9 */, 
     Insurance_id = 1 /* @p10 */, 
     Mother_id = NULL /* @p11 */, 
     Practice_id = 1 /* @p12 */, 
     Profession_id = NULL /* @p13 */, 
     Reputation_id = 1 /* @p14 */ 
WHERE Person_id = 3 /* @p15 */ 

如何優化執行時間?

編輯1

由於@csanchez的建議,我已經成功添加動態更新我的實體。現在當我將SQL查看到NH Profiler時,我得到了這個:

UPDATE Patient 
SET Father_id = 2 /* @p0 */ 
WHERE Person_id = 21 /* @p1 */ 

這是一個很多優化!但是,執行時間爲1852年...... O_O MS

在調試器中,我看到,它正在實施,需要時間的交易......我不知道爲什麼它這麼慢...

編輯2

每個病人有醫療照片,作爲字節數組存儲在表中。下面是創建表的SQL(由功能NHibernate完成)

CREATE TABLE Picture (
    Id    integer PRIMARY KEY AUTOINCREMENT, 
    Bitmap   blob, 
    Creation   datetime, 
    LastUpdate  datetime, 
    Notes   text, 
    IsImported  bool, 
    Tag_id   bigint, 
    Patient_id  bigint, 
    ThumbnailBitmap blob, 
    /* Foreign keys */ 
    FOREIGN KEY (Patient_id) 
    REFERENCES Patient(), 
    FOREIGN KEY (Tag_id) 
    REFERENCES "Tag"() 
); 

如果我把數據與DELETE Picture並重新啓動應用程序,更新是光速快。

看起來像nHibernate試圖變得聰明,並做一些減慢一切。但是,如果事件中,我使用此代碼執行一個純粹的SQL查詢,更新仍然需要超過一秒鐘:

using (var tx = this.Session.BeginTransaction()) 
{ 
    var sql = "UPDATE Patient SET Father_id = 2 WHERE Person_id = 21";  
    var query = this.Session.CreateSQLQuery(sql); 
    query.ExecuteUpdate(); 

    tx.Commit(); 
} 

回答

0

這是性能命中率僅爲與第一次提交到數據庫。 SQLite可能有一些起飛時間。

你說「會話每個方法」,但它看起來像你使用模塊級會話變量。 Session實例做得越多,緩存就會變得越慢。如果這將是更多的批處理操作,請考慮StatelessSession。

同時檢查NHibernate + Log4Net的日誌配置。日誌記錄越詳細,NH越緩慢。

+0

nHibernate只記錄從WARNING到FATAL的日誌。正如我所說的,動態代理會打開會話,調用方法並最終關閉會話。每次我調用這個方法時,這個簡單的更新需要2秒鐘。 –

0

每次更改數據時都不應該刷新會話。您應該讓NHibernate緩衝區更新並刷新批量更改。否則,他們會做出平滑的隱式操作,而不用擔心它。

+0

如果我刪除Flush(),那麼提交事務需要2秒 –

1

如果您更新的唯一東西是父母或母親,您可以在患者的映射文件中使用dynamic-update="true"