我知道这是一个受欢迎的问题,并且已经向其他人提出了各种解决方案,但我的略有不同。
首先它从两天前开始突然发生,NHibernate 层没有任何变化来解释这种行为变化。
我使用 dotTrace 并对其进行深入研究,发现某些缓存查询最多需要 70 秒才能执行(即返回国家对象列表的 GetAllCountries() 方法)。
对于这样一个没有外部引用的简单查询来说,70 秒是相当疯狂的。
dotTrace 显示它调用了应该立即返回列表的 CachedCountryService。相反,它最终会导致执行 70 秒读取的 CountryService。
数据库是mySQL。
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 配置,而不是代码,因为这两组查询使用相同的域模型是相同的。他们还使用相同的数据库和相同的数据库用户。