NHibernate ThenFetchMany 正在检索重复的子项

发布于 2024-11-10 14:58:12 字数 417 浏览 3 评论 0原文

我有一个父对象,其子集合包含一个元素,子集合包含一个包含 3 个元素的“孙子”集合。

我正在使用 NHibernate 从数据库加载父对象,如下所示

Parent parentObject = session.Query<Parent>()
    .FetchMany(x => x.Children)
    .ThenFetchMany(x => x.GrandChildren)
    .Where(x => x.Id = "someparentid")
    .Single();

我发现父对象上应该只有一个,但有重复的子对象(总共 3 个)。 (每个子对象正确附加了 3 个孙对象。)急切加载子对象集合只能正常工作。

你知道我如何实现加载完整的父对象而不需要重复的子对象吗?

I have a parent object with a child collection containing one element, the child collection contains a "grandchild" collection containing 3 elements.

I am loading the parent object from the database using NHibernate as follows

Parent parentObject = session.Query<Parent>()
    .FetchMany(x => x.Children)
    .ThenFetchMany(x => x.GrandChildren)
    .Where(x => x.Id = "someparentid")
    .Single();

What I'm finding is that there are duplicate children objects (3 in total) attached to the parent object when there should be only one. (There are 3 grandchild objects correctly attached to each child.) Eager loading the children collection only works correctly.

Do you know how I can achieve loading of the full parent object without duplicate children?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(4

晨曦慕雪 2024-11-17 14:58:12

如果将 Children 和 GrandChildren 映射为 set,则可以避免笛卡尔积。您需要将 Children 和 Grandchildren 定义为集合:

public class Parent
{
    ...
    public virtual ICollection<Child> Children { get; set; }
    ...
}

public class Child
{
    ...
    public virtual ICollection<GrandChild> GrandChildren { get; set; }
    ...
}

并在映射中(使用 FluentNHibernate):

public class ParentMapping : ClassMap<Parent>
{
    public ParentMapping()
    {
        ...
        HasMany(x => x.Children)
            .KeyColumn("ParentID")
            .Inverse
            .AsSet()
        ...
    }
}

public class ChildMapping : ClassMap<Child>
{
    public ChildMapping()
    {
        ...
        HasMany(x => x.GrandChildren)
            .KeyColumn("ChildID")
            .Inverse
            .AsSet()
        ...
    }
}

If you map Children and GrandChildren as set, you can avoid the cartesian product. You need to define Children and Grandchildren as collections:

public class Parent
{
    ...
    public virtual ICollection<Child> Children { get; set; }
    ...
}

public class Child
{
    ...
    public virtual ICollection<GrandChild> GrandChildren { get; set; }
    ...
}

And in the mapping (using FluentNHibernate):

public class ParentMapping : ClassMap<Parent>
{
    public ParentMapping()
    {
        ...
        HasMany(x => x.Children)
            .KeyColumn("ParentID")
            .Inverse
            .AsSet()
        ...
    }
}

public class ChildMapping : ClassMap<Child>
{
    public ChildMapping()
    {
        ...
        HasMany(x => x.GrandChildren)
            .KeyColumn("ChildID")
            .Inverse
            .AsSet()
        ...
    }
}
迷乱花海 2024-11-17 14:58:12

I was able to use the answer here using QueryOver, it correctly loads the objects while generating efficient SQL (selects per table instead of one huge join).

抹茶夏天i‖ 2024-11-17 14:58:12

如果您使用 Linq,您可以用以下方法简化它:

int parentId = 1;
var p1 = session.Query<Parent>().Where(x => x.ParentId == parentId);

p1
.FetchMany(x => x.Children)
.ToFuture();

sess.Query<Child>()
.Where(x => x.Parent.ParentId == parentId);
.FetchMany(x => x.GrandChildren)
.ToFuture();

Parent p = p1.ToFuture().Single();

详细说明如下: http://www.ienablemuch.com/2012/08/solving-nhibernate-thenfetchmany.html

If you are using Linq, you can simplify it with this:

int parentId = 1;
var p1 = session.Query<Parent>().Where(x => x.ParentId == parentId);

p1
.FetchMany(x => x.Children)
.ToFuture();

sess.Query<Child>()
.Where(x => x.Parent.ParentId == parentId);
.FetchMany(x => x.GrandChildren)
.ToFuture();

Parent p = p1.ToFuture().Single();

Detailed explanation here: http://www.ienablemuch.com/2012/08/solving-nhibernate-thenfetchmany.html

悟红尘 2024-11-17 14:58:12

你不能用 NHibernate 做到这一点(我认为你也不能用 EF4 做到这一点),因为你的结果是笛卡尔积。您将从所有表中获取所有结果。

NHibernate 不知道如何将两个集合的结果映射回根。因此,对于每个子代,您会得到相同数量的孙子代,并且对于每个孙子代,您最终会得到相同数量的子代。

You can't do it with NHibernate (I don't think you can do it with EF4 either) since your result is a Cartesian product. You're getting all results from all tables.

NHibernate doesn't know how to map the results from both collections back to the root. So for each Children, you get the same number of GrandChildren, and for each GrandChildren you end up with the same number of Children.

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