Nhibernate 急切获取引用时重复(多对一)

Nhibernate 急切获取引用时重复(多对一),nhibernate,fluent-nhibernate,nhibernate-mapping,hql,fluent-nhibernate-mapping,Nhibernate,Fluent Nhibernate,Nhibernate Mapping,Hql,Fluent Nhibernate Mapping,首先,是的,我使用的是DistincTrotentyResultTransformer 我有以下(Fluent NHibernate)映射: 所以无论什么原因,NH都会创建24秒的对象,而不是1秒 我猜它不知道如何将“join-fetch”(左侧或内部似乎无关紧要)映射到Reference(SecondObject中对ThirdObject的引用) 我有什么选择?我无法更改数据模型,但我确实需要加载所有数据模型 提前谢谢 只有在加载父项和子项时,Distinct root实体才起作用。对于孙子和

首先,是的,我使用的是DistincTrotentyResultTransformer

我有以下(Fluent NHibernate)映射:

所以无论什么原因,NH都会创建24秒的对象,而不是1秒

我猜它不知道如何将“join-fetch”(左侧或内部似乎无关紧要)映射到Reference(SecondObject中对ThirdObject的引用)

我有什么选择?我无法更改数据模型,但我确实需要加载所有数据模型


提前谢谢

只有在加载父项和子项时,Distinct root实体才起作用。对于孙子和曾孙来说,这是行不通的。问题是,您正在加载多个集合关联并返回一个大的
笛卡尔乘积

请阅读这篇文章,它解释了为什么会出现这种情况,并提出了解决办法

一些可能不会立即显现出来的东西将导致 笛卡尔积。这一点已在报告中指出,但我 我想我们都可以同意,虽然这可能是有原因的 行为,这是远远不够理想的


据我所知,笛卡尔积仅在加入平行关联时出现。例如,如果A有B1和B2,那么这将导致笛卡尔积。Ayende在他的博客中详细地展示了这种情况(从博客b left join fetch b.Posts left join fetch b.Users)。但如果A、B、C、D是分层的(就像我所做的那样),它们就不应该创建笛卡尔积。我面临的问题是,我有多对一、多对一、一对多、多对一的层次结构。对吗?不,我不相信这是对的,你正在加载多->一->多->一。查看生成的SQL,并对数据库运行此操作,以了解发生了什么情况。第三到第四个关系导致了多个集合关联,因此创建了24秒ObjectsKey,我认为这是第二到第三个关系。。你建议如何解决这个问题?我不知道该怎么做。Future在这方面会有所帮助。一级缓存中的对象似乎太多了!30k/50=600次到DB的行程!我真的认为你首先需要弄清楚为什么你需要这么多数据!
public FirstObjectMap() 
{
    Id(x => x.Id):
    HasMany<SecondObject>(x => x.SecondItems).KeyColumn("FirstObject_ID");
}

public SecondObjectMap()
{
    Id(x => x.Id).Column("ID");
    References(x => x.ThirdObject).Column("ThirdObject_ID");
}

public ThirdObjectMap()
{
    Id(x => x.Id).Column("ID");
    HasMany<D>(x => x.FourthItems).KeyColumn("ThirdObject_ID");
}

public FourthObjectMap()
{
    Id(x => x.Id).Column("ID");
}
var query = session.CreateQuery("select distinct first from " + 
   "FirstObject as first " +
   "left join fetch first.SecondItems as second " +
   "left join fetch second.ThirdObject as third " + 
   "left join fetch third.FourthItems as four where ...");

// This is not even needed as I'm using distinct in HQL
query.SetResultTransformer(new DistinctRootEntityResultTransformer());

var results = query.List<ReinsurableObject>();
1 FirstObject
  24 SecondObject (should be 1)
     24 x 1 ThirdObject (should be 1)
         24 x 1 x 24 FourthObject (should be 24)