C# 为什么未来不缓存在会话一级缓存中?

C# 为什么未来不缓存在会话一级缓存中?,c#,hibernate,caching,nhibernate,future,C#,Hibernate,Caching,Nhibernate,Future,我有一些“静态”只读实体,我只是用QueryOver().List()加载它们。它们的所有属性都不是“懒惰”。所以其中一些有N+1问题 我试图使用Future来避免N+1。但NH似乎认为实体属性是“懒惰的”。当我访问它们时,它甚至会一个接一个地从db重新加载实体(导致相同的N+1情况),尽管所有实体都是预先加载的,应该缓存在会话一级缓存中。下面是我如何操作的代码: var futures = new List<IEnumerable>(); futur

我有一些“静态”只读实体,我只是用
QueryOver().List()
加载它们。它们的所有属性都不是“懒惰”。所以其中一些有N+1问题

我试图使用
Future
来避免N+1。但NH似乎认为实体属性是“懒惰的”。当我访问它们时,它甚至会一个接一个地从db重新加载实体(导致相同的N+1情况),尽管所有实体都是预先加载的,应该缓存在会话一级缓存中。下面是我如何操作的代码:

        var futures = new List<IEnumerable>();
        futures.Add(s.QueryOver<DailyBonus>().Future<DailyBonus>());
        futures.Add(s.QueryOver<DailyBonusChestContent>().Future<DailyBonusChestContent>());
        // ... other entities ...

        // all queries should be sent with first enumeration
        // but I want to ensure everything is loaded 
        // before using lazy properties
        foreach (IEnumerable future in futures)
        {
            if (future.Cast<object>().Any(x => false)) break;
        }
        // now everything should be in cache, right?
        // so I can travel the whole graph without accessing db?
        Serializer.Serialize(ms, futures); // wow, N+1 here!          
var期货=新列表();
futures.Add(s.QueryOver().Future());
futures.Add(s.QueryOver().Future());
// ... 其他实体。。。
//所有查询都应与第一个枚举一起发送
//但我想确保所有东西都已加载
//在使用惰性属性之前
foreach(未来中的可数未来)
{
if(future.Cast().Any(x=>false))中断;
}
//现在所有东西都应该在缓存中,对吗?
//所以我可以在不访问db的情况下遍历整个图形?
序列化程序。序列化(ms,futures);//哇,这里是N+1!
我使用hibernatingrhinos profiler检查了这个行为


那么这里到底出了什么问题?

使用期货加载实体集合的唯一正确方法是使用
Fetch
,这意味着每个查询都要进行连接:

  var q = session.Query<User>().Where(x => x.Id == id);

    var lst = new List<IEnumerable>
    {
        q.FetchMany(x => x.Characters).ToFuture(),
        q.Fetch(x=>x.UpdateableData).ToFuture(),
        session.QueryOver<User>().Where(x => x.Id == id)
            .Fetch(x=>x.Characters).Eager
            .Fetch(x => x.Characters.First().SmartChallengeTrackers).Eager
            .Future()
    };

    var r = session.QueryOver<User>().Where(x => x.Id == id)
        .TransformUsing(Transformers.DistinctRootEntity)
        .Future();

    foreach (IEnumerable el in lst)
    {
        foreach (object o in el)
        {

        }
    }

    return r.ToArray();
var q=session.Query()。其中(x=>x.Id==Id);
var lst=新列表
{
q、 FetchMany(x=>x.Characters).ToFuture(),
q、 Fetch(x=>x.UpdateableData).ToFuture(),
session.QueryOver().Where(x=>x.Id==Id)
.Fetch(x=>x.Characters)。急切
.Fetch(x=>x.Characters.First().SmartChallengeTrackers)。急切
.Future()
};
var r=session.QueryOver()。其中(x=>x.Id==Id)
.变压器使用(变压器.距离)
.Future();
foreach(第一层中的IEnumerable el)
{
foreach(el中的对象o)
{
}
}
返回r.ToArray();
它仍然比在一个查询中连接所有内容要好-NHibernate不必解析由join x join x join x join x join引入的数千行

您可以将普通选择查询(不带
获取
)添加到同一批中,但它们不会用于检索其他实体上的集合