加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何使用NHibernate加载大型复杂对象图

发布时间:2020-12-15 17:16:56 所属栏目:百科 来源:网络整理
导读:给定一个像这样的对象图: A { IEnumB }B { IEnumC,IEnumD,IEnumE,... }C { IEnumX } 如何在没有N 1问题的情况下急切加载整个对象图? 这是我最终要执行的查询的伪代码: var a = Session.GetA(1); // Query 1var b_Ids = foreach(b in A.B's) = Select(b.Id
给定一个像这样的对象图:

A { IEnum<B> }
B { IEnum<C>,IEnum<D>,IEnum<E>,... }
C { IEnum<X> }

如何在没有N 1问题的情况下急切加载整个对象图?

这是我最终要执行的查询的伪代码:

var a = Session.Get<A>(1); // Query 1
var b_Ids = foreach(b in A.B's) => Select(b.Id); // Query 2
var c = Session.CreateQuery("from C where B in (b_Ids)").Future<C>(); // Query 3
var d = Session.CreateQuery("from D where B in (b_Ids)").Future<D>(); // Query 3
var e = Session.CreateQuery("from E where B in (b_Ids)").Future<E>(); // Query 3

// Iterate through c,d,e,... find the correct 'B' parent,add to collection manually

我使用这种方法的问题是,当我将’C’,’D’和’E’的实例添加到父’B’的相应集合时,该集合仍然被代理,何时.调用Add(),代理初始化自己并执行更多查询;我认为NHibernate无法看到我已经拥有一级缓存中的所有数据,这是可以理解的.

我尝试通过在Add方法中执行以下操作来解决此问题:

void Add(IEnum<C>)
{
    _collection = new Collection<C>(); // replace the proxied instance to prevent initialization
    foreach(c) => _collection.Add(c);
}

这给了我一个我想要的最佳查询策略,但是后来在做持久性时赶上了我(NHibernate跟踪原始集合的-ref,从我能说的地方).

所以我的问题是,如何在没有N 1的情况下为孩子的孩子加载一个复杂的图表?我到目前为止唯一遇到的就是加入B-C,B-D,B-E,这在我的情况下是不可接受的.

我们使用NH 2.1.2和FluentHN进行映射.升级到NH的v3或使用hbm /存储过程/任何不在桌面之外的东西.

更新:
其中一条评论引用了一种加入方法,我确实遇到了一个演示这种方法的博客.这种解决方法在我们的情况下是不可接受的,但它可能会帮助其他人:Eager fetch multiple child collections in 1 round trip with NHibernate

更新2:
乔丹的回答让我看到了与我的问题相关的以下帖子:Similar Question和Ayende’s blog.此时待定的问题是“如何在没有往返路径的情况下执行子选择”.

更新3:
即使subselect解决方案不是最优的,我也接受了Jordan的回答.

解决方法

您可以使用可在映射文件中设置的SubSelect提取.这将避免N 1和笛卡尔积.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读