0

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

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

我使用 dotTrace 并对其进行深入研究,发现某些缓存查询最多需要 70 秒才能执行(即返回国家对象列表的 GetAllCountries() 方法)。

对于这样一个没有外部引用的简单查询来说,70 秒是相当疯狂的。

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

数据库是mySQL。

dotTrace 报告的附加图像

dotTrace 报告的附加图像

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();
        }
    }

Initializer 不会影响 country 对象,尽管 Office 和 Account 用于另一个 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 个相同查询,需要 1 秒!

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

4

2 回答 2

0

终于解决了这个问题。

它与 NHibernate 无关!这就是为什么它如此不可能解决的原因。

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

当我卸载它并重新安装它时,它会将正确的 DLL 版本(稍旧的版本)放在适当的位置,这使项目能够以闪电般的速度运行!

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

于 2013-09-10T11:06:40.713 回答
0

从您的 dotTrace 屏幕截图中,请注意这InitializeNonLazyCollections几乎占用了所有时间。

DisableLazyLoadConvention应用的不仅仅是Office. 它被应用于ClassMap与 相同的程序集中的所有 s OfficeMapping。约定用于在整个应用程序中应用宽画笔笔划中的映射。例如,您可以使用它们来表示“每当您看到DateTime名称以 'Utc' 结尾的属性时,使用.CustomType("UtcDateTime").

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

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

于 2013-09-04T16:26:21.733 回答