休眠自引用性能
本文关键字:性能 自引用 休眠 | 更新日期: 2023-09-27 17:56:27
我有一个看起来像这样的模型:
public class ComponentAttributeDto
{
public virtual long ComponentAttributeId { get; set; }
public virtual ComponentAttributeDto ParentComponentAttributeDto { get; set; }
public virtual string ComponentAttributeName { get; set; }
public virtual string Value { get; set; }
public virtual DataType DataType { get; set; }
public virtual IList<ComponentAttributeDto> ChildComponentAttributes { get; set; }
}
映射文件为:
public class ComponentAttributeMapping : ClassMap<ComponentAttributeDto>
{
public ComponentAttributeMapping()
{
Table("ComponentAttributes");
Id(x => x.ComponentAttributeId)
.GeneratedBy.Identity();
References(x => x.ParentComponentAttributeDto)
.Column("ParentComponentAttributeId");
HasMany(x => x.ChildComponentAttributes)
.Fetch.Select()
.Inverse()
.Cascade.AllDeleteOrphan()
.KeyColumn("ParentComponentAttributeId");
Map(x => x.ComponentAttributeName)
.Length(50);
Map(x => x.Value)
.Length(1500);
Map(x => x.DataType)
.Length(20);
}
}
当使用大约 4 级深度的大型数据集加载它时,性能很糟糕。运行探查器时,我注意到它是否为我要查找的数据的表中的每个值执行 select 语句。有没有办法提高性能以在表上执行某种类型的联接或其他操作?
您可以使用批处理大小来预取实例,从而大大减少查询数量。
映射(不确定同时是否支持Fluent):
HasMany(x => x.ChildComponentAttributes)
.Fetch.Select()
.SetAttribute("batch-size", "20")
.Inverse()
.Cascade.AllDeleteOrphan()
.KeyColumn("ParentComponentAttributeId");
如果您有 Root 属性,则可以一次查询整个树。
public class ComponentAttributeDto
{
public virtual ComponentAttributeDto ParentComponentAttributeDto { get; private set; }
public virtual ComponentAttributeDto Root
{
get
{
if (ParentComponentAttributeDto == null)
{
return this;
}
else
{
return ParentComponentAttributeDto.Root;
}
}
private set
{ /* just for NH to call it */ }
}
// ....
}
HasMany(x => x.Children).AsSet()。SetAttribute("batch-size", "20")
查询
session.CreateQuery(
@"from ComponentAttributeDto
where Root = :root"
.SetEntity(root);
实际上应该只导致一个查询。不确定NH是否实际上没有对列表(ChildComponentAttributes)执行查询,但值得一试。
您是否需要同时完成整个数据结构?通常,当我遇到这个问题时,我只是从nHibernate中取出映射处理并自己处理它。为类创建一个名为 getChildren() 的方法,并让它在调用时运行查询。如果要添加子记录,请添加另一个名为 addChild() 的方法,并使其使用自己的父 ID 进行实例化。
查询时,您可以急切地获取层次结构。您可以通过在查询中使用预先获取选项来执行此操作:
Session.QueryOver<ComponentAttributeDto>
.Fetch(a => a.ChildComponentAttributes).Eager
下到您要获取的级别。