NHibernate ThenFetchMany is retrieving duplicate children

余生长醉 提交于 2019-12-07 05:06:24

问题


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?


回答1:


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()
        ...
    }
}



回答2:


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).




回答3:


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.




回答4:


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



来源:https://stackoverflow.com/questions/6194734/nhibernate-thenfetchmany-is-retrieving-duplicate-children

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!