NHibernate IsUpdateNecessary需要花费大量时间

时间:2011-07-23 20:55:04

标签: performance nhibernate castle-activerecord

我的C#3.5应用程序使用SQL Server 2008 R2,NHibernate和CastleProject ActiveRecord。应用程序将电子邮件及其附件导入数据库。在新会话和事务范围内通过50封电子邮件保存电子邮件和附件,以确保它们不存储在内存中(某些邮箱中可能有100K的电子邮件)。

最初电子邮件保存得非常快。但是,接近20K的电子邮件性能会急剧下降。使用dotTrace我得到了以下图片:

enter image description here

显然,当我保存附件时,NHibernate会尝试查看它是否真的应该保存它,并可能与会话中的其他附件进行比较。为此,它逐字节地比较它们几乎需要500秒(对于图片上的快照)和600M枚举器操作。

所有这些看起来都很疯狂,特别是当我确定SaveAndFlush确实应该保存附件而不进行任何检查时:我确定它是新的并且应该保存。

然而,我无法弄清楚,如何指示NHibernate避免这种检查(IsUpdateNecessary)。请指教。

P.S。我不确定,但是可能看起来接近20K的性能下降与内存中有一些旧邮件无关:我注意到在我使用的邮箱中,较大的电子邮件存储的时间比较小,所以问题可能只在于附件比较。

更新 看起来我需要像StatelessSessionScope这样的东西,但即使在CastleProject网站上也没有文档!如果我做了像

这样的事情
using (TransactionScope txScope = new TransactionScope())
using (StatelessSessionScope scope = new StatelessSessionScope())
{
  mail.Save();
}

失败,但无状态会话不支持Save。我应该将对象插入到会话中,但是我没有任何Session(只有SessionScope,它只能为SessionScope添加单个OpenSession方法,它接受奇怪的参数)。

2 个答案:

答案 0 :(得分:1)

可能是我在那篇长篇文章中错过了它,但您是否使用无状态会话导入数据?使用它可以防止大量检查,并绕过第一级缓存,从而使用最少的资源。

答案 1 :(得分:1)

看起来我找到了一个简单的解决方案:对于我的类附件,导致最大的性能损失,我覆盖了以下方法:

protected override int[] FindDirty(
    object id, 
    System.Collections.IDictionary previousState, 
    System.Collections.IDictionary currentState, NHibernate.Type.IType[] types)
  {
    return new int[0];
  }

因此,脏检查总是认为它很脏,并且不会进行那种疯狂的每字节比较。

相关问题