Fluent NHibernate - 批量查询子属性集合而不是单独查询
我有一个实体,上面有多个其他实体的集合,我想立即加载它们,最好是批量加载。下面的示例设置:
public Entity1
{
public virtual int Prop1 {get;set;}
public virtual string Prop2 {get;set;}
public virtual IList<Entity2> Prop3 {get;set;}
public virtual IList<Entity3> Prop4 {get;set;}
}
public Entity2
{
public virtual int Prop1 {get;set;}
public virtual string Prop2 {get;set;}
}
public Entity3
{
public virtual int Prop1 {get;set;}
public virtual string Prop2 {get;set;}
public virtual IList<Entity1> Prop3 {get;set;}
}
映射实体:
public class Entity1Map : ClassMap<Entity1>
{
public ClientMap()
{
Table("Clients");
Id(m => m.Prop1);
Map(m => m.Prop2);
}
}
public class Entity1Map : ClassMap<Entity1>
{
public Entity1Map()
{
Table("Entity1Table");
Id(m => m.Prop1);
Map(m => m.Prop2);
HasMany(m => m.Prop3).KeyColumn("Prop1").LazyLoad().NotFound.Ignore();
HasMany(m => m.Prop4).KeyColumn("Prop1").LazyLoad().NotFound.Ignore();
}
}
public class Entity2Map : ClassMap<Entity2>
{
public Entity2Map()
{
Table("Entity2Table");
Id(m => m.Prop1);
Map(m => m.Prop2);
}
}
public class Entity3Map : ClassMap<Entity3>
{
public Entity3Map()
{
Table("Entity3Table");
Id(m => m.Prop1);
Map(m => m.Prop2);
HasOne(m => m.Prop3).ForeignKey("Prop1").LazyLoad();
}
}
并使用以下方式查询数据库:
var query = session.CreateCriteria<Entity1>()
.CreateCriteria("Prop3", "prop3", JoinType.InnerJoin)
.Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
.SetFetchMode("Prop3", FetchMode.Join)
.SetFetchMode("Prop4", FetchMode.Join);
var clients = query.Future<Entity1>().ToList();
//Do other things here with eager loaded collections
当我在数据库中查询实体 1 时,我得到实体 1 集合的返回 - 正如我所期望的那样,但是,使用 NProf,我可以看到为每个实体 2/3 创建单个查询,以访问数据库并单独收集它们,这意味着实体 1 的 10 行返回将触发 3 倍的查询。有没有办法对急切加载查询进行批处理,这样每个查询都不会执行
SELECT * FROM <table> WHERE id = XXX
SELECT * FROM <table> WHERE id = YYY
SELECT * FROM <table> WHERE id = ZZZ
NHibernate 会产生更像这样的结果
SELECT * FROM <table> WHERE id IN (XXX,YYY,ZZZ)
,因此不需要多次查询数据库?
非常感谢任何帮助,如果需要更多详细信息,请告诉我。
I have an entity with multiple collections of other entities on it, and I'd like to eager load them, ideally in one batch. Example setup below:
public Entity1
{
public virtual int Prop1 {get;set;}
public virtual string Prop2 {get;set;}
public virtual IList<Entity2> Prop3 {get;set;}
public virtual IList<Entity3> Prop4 {get;set;}
}
public Entity2
{
public virtual int Prop1 {get;set;}
public virtual string Prop2 {get;set;}
}
public Entity3
{
public virtual int Prop1 {get;set;}
public virtual string Prop2 {get;set;}
public virtual IList<Entity1> Prop3 {get;set;}
}
Mapping for Entities:
public class Entity1Map : ClassMap<Entity1>
{
public ClientMap()
{
Table("Clients");
Id(m => m.Prop1);
Map(m => m.Prop2);
}
}
public class Entity1Map : ClassMap<Entity1>
{
public Entity1Map()
{
Table("Entity1Table");
Id(m => m.Prop1);
Map(m => m.Prop2);
HasMany(m => m.Prop3).KeyColumn("Prop1").LazyLoad().NotFound.Ignore();
HasMany(m => m.Prop4).KeyColumn("Prop1").LazyLoad().NotFound.Ignore();
}
}
public class Entity2Map : ClassMap<Entity2>
{
public Entity2Map()
{
Table("Entity2Table");
Id(m => m.Prop1);
Map(m => m.Prop2);
}
}
public class Entity3Map : ClassMap<Entity3>
{
public Entity3Map()
{
Table("Entity3Table");
Id(m => m.Prop1);
Map(m => m.Prop2);
HasOne(m => m.Prop3).ForeignKey("Prop1").LazyLoad();
}
}
And querying the database with:
var query = session.CreateCriteria<Entity1>()
.CreateCriteria("Prop3", "prop3", JoinType.InnerJoin)
.Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
.SetFetchMode("Prop3", FetchMode.Join)
.SetFetchMode("Prop4", FetchMode.Join);
var clients = query.Future<Entity1>().ToList();
//Do other things here with eager loaded collections
When I query the database for entity 1, I get a return of a collection of Entity 1 - as I expect I might, however, using NHProf, I can then see a single query being created for each of entity 2/3 to go to the database and collect them individually, meaning that a 10 row return of entity 1 will fire 3 times that many queries. Is there a way to batch the eager loading queries, so that instead of each of them doing a
SELECT * FROM <table> WHERE id = XXX
SELECT * FROM <table> WHERE id = YYY
SELECT * FROM <table> WHERE id = ZZZ
NHibernate will produce something more like
SELECT * FROM <table> WHERE id IN (XXX,YYY,ZZZ)
And thus not need to query the database so many times?
Any help much appreciated, let me know if there is more detail required.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个想法是在单独的未来查询中进行每个连接。你的查询很混乱,我的也是这样:
The idea is to make each join in a separate future query. Your query is a mess so is mine: