2012-11-04 83 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"