C# 带有连接的Queryover动态获取

C# 带有连接的Queryover动态获取,c#,nhibernate,fetch,future,queryover,C#,Nhibernate,Fetch,Future,Queryover,我正在尝试使用nhibernate进行新查询,并发现一个新问题:( 以此为模型: public class D { int id; } public class C { int id; } public class B { int id; ICollection<C> Cs; ICollection<D> Ds; } public class A { int id; ICollection<B> Bs; } 我看到执行

我正在尝试使用nhibernate进行新查询,并发现一个新问题:(

以此为模型:

public class D { int id; }
public class C { int id; }
public class B {
    int id;
    ICollection<C> Cs;
    ICollection<D> Ds;
}
public class A {
    int id;
    ICollection<B> Bs;
}
我看到执行了许多查询,并且
Cs
Ds
抛出了错误

我发现并阅读到,如果没有leftJoin,那么将第一部分切换到以下内容:

B BB= null;
IEnumerable<A> query =_session.QueryOver<A>()
        .Fetch(a => a.Bs).Eager
        .Left.JoinAlias(a => a.Bs, () => BB)
        .Where(() => BB.Id == idB)
        .Future<A>();
虽然这不是:

IEnumerable<A> query = _session.QueryOver<A>()
                        .JoinQueryOver(a => a.Bs)
                        .Where(b => b.Id == idB)
                        .Future<A>();

foreach (Expression<Func<A>, object>> field in eagerFields)
    _session.QueryOver<A>()
        .Fetch(field).Eager
        .Future<A>();

return query.First();   
IEnumerable query=\u session.QueryOver()
.JoinQueryOver(a=>a.Bs)
.其中(b=>b.Id==idB)
.Future();
foreach(表达式>字段中的字段)
_session.QueryOver()
.抓取(字段)
.Future();
返回query.First();

以这种方式调用:
Read(12,a=>a.Bs,a.Bs.First().Cs,a.Bs.First().Ds)

看看您的实际问题,急切加载,我不明白您为什么要将未来放在这种方式中。您当前的代码在逻辑上应该是错误的:它发出一个带有筛选条件的查询,然后是一堆“加载所有具有急切加载属性的实体”查询

如果获取的属性不是集合(或者只有一个是集合),则应这样编写:

IQueryOver<A, A> query = _session.QueryOver<A>()
    .JoinQueryOver(a => a.Bs)
    .Where(b => b.Id == idB);

foreach (Expression<Func<A>, object>> field in eagerFields)
    query = query
        .Fetch(field).Eager;

return query.List().First();
请注意,对于NHibernate 5及以上版本,如果您的数据提供程序实际上不支持future(在单个SQL命令中有多个查询),则未显式执行的future将在不执行的情况下被丢弃。(以前的版本在
future
调用时立即执行future查询,数据提供程序实际上不支持这些查询。)

如果要在数据提供程序不支持期货的情况下执行,请将最后一行更改为:

if (queries.Count == 0)
    return queryBase.List().First();

List<A> result;
foreach (var q in queries)
{
    // Using the IFutureEnumerable directly as an IEnumerable is deprecated.
    result = q.GetEnumerable()
        // Due to a bug, GetEnumerable is not yet enough to trigger execution.
        .ToList();
}

return result.First();
if(querys.Count==0)
返回queryBase.List().First();
列出结果;
foreach(查询中的var q)
{
//不推荐将IFutureEnumerable直接用作IEnumerable。
结果=q.GetEnumerable()
//由于一个bug,GetEnumerable还不足以触发执行。
.ToList();
}
返回result.First();

我的方法:永远不要使用即时抓取…始终依赖于相关集合延迟加载-使用本机批处理-请参阅或问题在Web表单中我读了很多关于会话生命周期的内容,但最好的折衷办法是在页面加载中即时加载我需要的所有内容,然后立即关闭会话。除此之外,所有方法都可以正常工作,并且我的应用程序只有90%的可用空间以这种方式完成不,这可能是EF的最佳折衷方案,但不是NHibernate。您的阅读文章是否通过Radim链接?解释原因。如果您在关闭会话后使用实体,那么您需要在关闭之前触发延迟加载,最终通过迭代您的其他实体。但通常我宁愿使用Radim获取视图模型实体数据,然后关闭会话,并仅从该点使用视图模型。仍在使用webForm,没有MVC:(以前的版本在会话打开时为每个所需的集合执行.count(),但将全部切换为动态模式(请参阅)。除了更新了propertyquestion的第二级以表明问题不在急取中,而是在动态创建未来查询时,所有操作都正常
IEnumerable<A> query = _session.QueryOver<A>()
.Left.JoinAlias(a => a.Bs, () => BB)
.Where(() => BB.Id == IdB)
.Fetch(a => a.Bs).Eager
.Fetch(a => a.Bs.First().Cs).Eager
.Future<A>();
return query.First();
IEnumerable<A> query = _session.QueryOver<A>()
                        .JoinQueryOver(a => a.Bs)
                        .Where(b => b.Id == idB)
                        .Future<A>();

foreach (Expression<Func<A>, object>> field in eagerFields)
    _session.QueryOver<A>()
        .Fetch(field).Eager
        .Future<A>();

return query.First();   
IQueryOver<A, A> query = _session.QueryOver<A>()
    .JoinQueryOver(a => a.Bs)
    .Where(b => b.Id == idB);

foreach (Expression<Func<A>, object>> field in eagerFields)
    query = query
        .Fetch(field).Eager;

return query.List().First();
var queryBase = _session.QueryOver<A>()
    .JoinQueryOver(a => a.Bs)
    .Where(b => b.Id == idB);

var queries = new List<IEnumerable<A>>();
foreach (Expression<Func<A>, object>> field in eagerFields)
    queries.Add(queryBase
        .Fetch(field).Eager
        .Future());

return queries.Count == 0 ? queryBase.List().First() : queries[0].First();
if (queries.Count == 0)
    return queryBase.List().First();

List<A> result;
foreach (var q in queries)
{
    // Using the IFutureEnumerable directly as an IEnumerable is deprecated.
    result = q.GetEnumerable()
        // Due to a bug, GetEnumerable is not yet enough to trigger execution.
        .ToList();
}

return result.First();