NHibernate突然非常缓慢 - 莫名其妙的行为

时间:2013-09-04 15:05:34

标签: c# performance nhibernate asp.net-mvc-4 dottrace

我知道这是一个受欢迎的问题,并且已经向其他人提出了各种解决方案,但我的情况略有不同。

首先它从两天前开始突然发生,NHibernate层没有任何变化来解释这种行为的变化。

我使用了dotTrace并向下钻取,发现某些缓存查询最多需要70秒才能执行(即返回国家/地区对象列表的GetAllCountries()方法)。

对于没有外部引用的简单查询,70秒非常疯狂。

dotTrace显示它调用了CachedCountryService,它应该立即返回列表。相反,它最终会导致CountryService执行70秒的读取。

数据库是mySQL。

dotTrace报告的附加图片

An attached image of the dotTrace report

Country对象如下所示:

   public class CountryMapping : ClassMap<Country>
    {
        public CountryMapping()
        {
            Table("ma_tbl_country");

            Id(t => t.Id, "id");
            Map(t => t.Code, "code");
            Map(t => t.Name, "name");
            Map(t => t.Match, "`match`");

            References(t => t.RiskGroup).Column("RiskId");

            HasManyToMany(t => t.PaymentOptions)
                .Table("ma_tbl_country_payment_option")
                .ParentKeyColumn("country_id")
                .ChildKeyColumn("payment_option_id").Cascade.SaveUpdate();
        }
    }

初始化程序不会影响国家/地区对象,尽管Office和帐户用于其他执行效果非常差的NHibernate查询(需要30秒)。

 public NHibernateInitializer()
        {
            base.
            ExtraConfiguration =
                t =>
                    t.Mappings(s => s.FluentMappings.AddFromAssemblyOf<DAL.Mappings.OfficeMapping>().Conventions.Add(typeof(DisableLazyLoadConvention)))
                    .Mappings(s => s.FluentMappings.AddFromAssemblyOf<AccountMapping>().Conventions.Add(AutoImport.Never()));
        }

DefaultLazyConvention是执行此操作的内部库的一部分:

  public class DisableLazyLoadConvention : IHibernateMappingConvention, IConvention<IHibernateMappingInspector, IHibernateMappingInstance>, IConvention
  {
    public void Apply(IHibernateMappingInstance instance)
    {
      instance.Not.DefaultLazy();
    }
  }

更新:

我添加了SQL级别的分析,结果正在缓冲。

我有两个不同的项目运行相同的几乎代码,我在缓慢的项目中获得324个SQL查询需要100秒才能运行,然后在另一个项目中获得324个IDENTICAL查询需要1秒!

所以我认为问题是NHibernate配置,而不是代码,因为这两组查询使用相同的域模型是相同的。他们也使用相同的数据库和相同的数据库用户。

2 个答案:

答案 0 :(得分:0)

从您的dotTrace屏幕截图中,请注意InitializeNonLazyCollections几乎所有时间都在使用。

DisableLazyLoadConvention的应用不仅仅是Office。它将应用于与ClassMap相同的程序集中的所有OfficeMapping。约定用于在整个应用程序中以宽画笔描边应用映射。例如,您可以使用它们来说&#34;当您看到名称以&#39; Utc&#39;结尾的DateTime属性时,请使用.CustomType("UtcDateTime")进行映射。&#34 ;

如果您需要将特殊映射应用于一个类,请在ClassMap(用于流畅映射)或IAutoMappingOverride(用于自动映射)中执行此操作。如果要更改每个类的映射,请在使用约定时进行映射。

从您的NHibernate初始化代码中删除.Conventions.Add(typeof(DisableLazyLoadConvention)),并将其替换为.Not.LazyLoad()中对OfficeMapping的更有针对性的调用。

答案 1 :(得分:0)

最终解决了这个问题。

这与NHibernate无关!这就是为什么它无法解决的原因。

问题是由名为Combres的这个包引起的。它通过Nuget安装,具有很多依赖性。在我的一个项目中,其中一个依赖项的版本略高于预期。

当我卸载并重新安装它时,它会放置正确的DLL版本(稍微较旧的版本)并使项目快速闪烁!

如果有人遇到这么难的问题,我希望这可以帮助他们解决问题。