Fluent NHibernate - 批量查询子属性集合而不是单独查询

发布于 2024-12-27 15:19:19 字数 2492 浏览 2 评论 0原文

我有一个实体,上面有多个其他实体的集合,我想立即加载它们,最好是批量加载。下面的示例设置:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不羁少年 2025-01-03 15:19:19

这个想法是在单独的未来查询中进行每个连接。你的查询很混乱,我的也是这样:

session.CreateCriteria<Entity1>()
    .CreateCriteria("Prop3", "prop3", JoinType.InnerJoin)
    .Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
    .Future<Entity1>();

session.CreateCriteria<Entity1>()
    .Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
    .SetFetchMode("Prop2", FetchMode.Join)
    .Future<Entity1>();

var query = session.CreateCriteria<Entity1>()
    .Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
    .SetFetchMode("Prop4", FetchMode.Join)
    .Future<Entity1>();

var clients = query.ToList();

The idea is to make each join in a separate future query. Your query is a mess so is mine:

session.CreateCriteria<Entity1>()
    .CreateCriteria("Prop3", "prop3", JoinType.InnerJoin)
    .Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
    .Future<Entity1>();

session.CreateCriteria<Entity1>()
    .Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
    .SetFetchMode("Prop2", FetchMode.Join)
    .Future<Entity1>();

var query = session.CreateCriteria<Entity1>()
    .Add(Restrictions.Eq(Projections.Property("Prop2"), "Criteria!"))
    .SetFetchMode("Prop4", FetchMode.Join)
    .Future<Entity1>();

var clients = query.ToList();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文