我使用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();
}
nHibernate只記錄從WARNING到FATAL的日誌。正如我所說的,動態代理會打開會話,調用方法並最終關閉會話。每次我調用這個方法時,這個簡單的更新需要2秒鐘。 –