C# 使用NHibernate加载子财产和孙子孙女
我有一个类模型图,如下所示C# 使用NHibernate加载子财产和孙子孙女,c#,nhibernate,fetch,eager-loading,linq-to-nhibernate,C#,Nhibernate,Fetch,Eager Loading,Linq To Nhibernate,我有一个类模型图,如下所示 A { ISet<B> Bset; int Id;} B { ISet<C> Cset; D Dprop; } D { int Id; } A{ISet Bset;int Id;} B{ISet Cset;D Dprop;} D{int Id;} 所有属性都配置为延迟加载。我试图编写一个查询来加载所有的图形,从a开始。理想情况下,它应该是 var result = (from conf in s.Query<A>()
A { ISet<B> Bset; int Id;}
B { ISet<C> Cset; D Dprop; }
D { int Id; }
A{ISet Bset;int Id;}
B{ISet Cset;D Dprop;}
D{int Id;}
所有属性都配置为延迟加载。我试图编写一个查询来加载所有的图形,从a开始。理想情况下,它应该是
var result = (from conf in s.Query<A>()
.FetchMany(x => x.Bset)
.ThenFetch(x => x.Dprop)
// line below doesn't work, because x
//is a D object here, and not a "B", as I would like
.ThenFetchMany(x => x.Cset)
where conf.Id == 42
select conf).SingleOrDefault();
var result=(来自s.Query()中的conf)
.FetchMany(x=>x.Bset)
.ThenFetch(x=>x.Dprop)
//下面的行不起作用,因为x
//这里是一个D对象,而不是我想要的“B”
.ThenFetchMany(x=>x.Cset)
其中conf.Id==42
选择conf.SingleOrDefault();
因此,当我试图获取Cset关联时,我需要做的是“上升一级”。有人知道怎么做吗
我正在使用Nhibernate 4.1.0。您必须从
FetchMany
重新开始
var result = (from conf in s.Query<A>()
.FetchMany(x => x.Bset)
.ThenFetch(x => x.Dprop)
.FetchMany(x => x.Bset)
.ThenFetchMany(x => x.Cset)
where conf.Id == 42
select conf).SingleOrDefault();
var result=(来自s.Query中的conf
如果需要关闭会话,然后使用实体,则必须通过对其延迟加载的属性调用NHibernateUtil.Initialize()
,在实体上循环来触发延迟加载。由于延迟加载批处理,它不会对已加载的实体执行任何操作。
另一种选择是在关闭会话之前将实体转换为视图模型。Frédréric回答说,一种方法是重复FetchMany子句,从图中的第一个实体开始再次到达Cset:
var result = (from conf in s.Query<A>()
.FetchMany(x => x.Bset).ThenFetch(x => x.Dprop)
.FetchMany(x => x.Bset).ThenFetchMany(x => x.Cset)
where conf.Id == 42
select conf).SingleOrDefault();
var result=(来自s.Query()中的conf)
.FetchMany(x=>x.Bset)。然后fetch(x=>x.Dprop)
.FetchMany(x=>x.Bset)。然后FetchMany(x=>x.Cset)
其中conf.Id==42
选择conf.SingleOrDefault();
使用集合进行关联,该解决方案不会在生成的SQL或NHibernate返回的对象中产生笛卡尔乘积
另一种解决方案是使用未来查询,该查询将在实际查询被激发时执行(就在它之前):
var queryAux=(来自s.Query()中的conf)
.FetchMany(x=>x.Bset)
.ThenFetch(x=>x.Dprop)
其中conf.Id==42选择conf.ToFuture();
var result=(来自s.Query()中的conf)
.FetchMany(x=>x.Bset)
.ThenFetch(x=>x.Dprop)
其中conf.Id==42
选择conf.SingleOrDefault();
这样,将向数据库激发2个查询,但它也可以工作。您可以使用'longhand'LINQ并使用let
关键字吗?即let b=Bset
我该如何做?我尝试了类似的方法(从s.Query()中的conf.FetchMany(x=>x.Bset)。然后FetchMany(x=>x.Dprop)let b=(从s.Query()中的ent.FetchMany(x=>Cset)其中ent.A.Id==42选择结束)其中conf.Id==42选择conf.SingleOrDefault();但它不会在let b=(…)中执行子查询。我不确定。我是从QueryOver
得到这个想法的,在那里你可以使用变量作为别名,然后在查询中引用它们。我希望let
关键字可以提供相同的功能。
var queryAux = (from conf in s.Query<A>()
.FetchMany(x => x.Bset)
.ThenFetch(x => x.Dprop)
where conf.Id == 42 select conf).ToFuture();
var result = (from conf in s.Query<A>()
.FetchMany(x => x.Bset)
.ThenFetch(x => x.Dprop)
where conf.Id == 42
select conf).SingleOrDefault();