Fluent Nhibernate:同时获取集合中的集合

Fluent Nhibernate:同时获取集合中的集合,nhibernate,fluent-nhibernate,task-parallel-library,Nhibernate,Fluent Nhibernate,Task Parallel Library,我需要急切地获取一个包含集合集合等的实体,以便可以并发地处理数据(一个包含许多黄色实体的实体,每个实体都有许多子黄色实体)。所需的关键代码是: NHibernateUtil.Initialize(fetchedThings); (参见下面的公认答案。)当前方法存在几个问题。让我重新来看看这个问题 据我所知,您希望检索事物,其中包含多对一蓝色实体,以及黄色实体的集合,而黄色实体的集合又包含亚黄色实体 您不应该使用连接获取、转换器和循环,而应该查看实体和集合的类型 对于BlueEntity、Thi

我需要急切地获取一个包含集合集合等的实体,以便可以并发地处理数据(一个包含许多黄色实体的实体,每个实体都有许多子黄色实体)。所需的关键代码是:

NHibernateUtil.Initialize(fetchedThings);

(参见下面的公认答案。)

当前方法存在几个问题。让我重新来看看这个问题

据我所知,您希望检索
事物
,其中包含多对一
蓝色实体
,以及
黄色实体的集合
,而黄色实体的集合又包含
亚黄色实体

您不应该使用
连接获取
、转换器和循环,而应该查看实体和集合的类型

对于
BlueEntity
Thing.YellowEntities
YellowEntities.SubYellowEntities
设置了良好的批量大小,您应该根本不需要TPL材料

如果结果是这样,您将无法返回安全使用的实体,因为它们必须与单个会话关联才能使用,并且会话不是线程安全的。

解决方案(如果您可以改进此方案,请继续并将修订作为答案发布):运行时间为17秒(从97秒减少)在8个处理器上获得正确的结果。请记住,绝大多数时间都花在计算上,而不是等待Nhibernate返回

var fetchedThings = new List<Thing>();
var sessFT = Session.SessionFactory.OpenSession();
Task getThingsTask = new Task(() =>
   {
       fetchedThings = sessFT.CreateQuery(@" from Thing t " +
                             " inner join fetch t.BlueEntity " )
                             .SetResultTransformer(Transformers.DistinctRootEntity)
                             .List<Thing>();
        NHibernateUtil.Initialize(fetchedThings);
    });
getThingsTask.Start();

var fetchedYellows = new List<YELLOWEntity>();
var sessFY = Session.SessionFactory.OpenSession();
Task getYellowsTask = new Task(() =>
   {
        fetchedYellows = sessFY.CreateQuery(@" from YELLOWEntity y " +
                             " left join fetch y.SubYellowEntities " + ... )
                             .SetResultTransformer(Transformers.DistinctRootEntity)
                             .List<YELLOWEntity>();
        NHibernateUtil.Initialize(fetchedThings);
    });
getYellowsTask.Start();

getThingsTask.Wait();
getYellowsTask.Wait();

Parallel.ForEach(fetchedThings, thing =>
{
    thing.YELLOWEntities = fetchedYellows.Where(y=>y.Thing.Id == thing.Id).ToList();
    ...
    //...inner foreach() loop through 'YELLOWthings'... doing threadsafe stuff
    ...
});

//dispose the temp sessions
var fetchedThings=new List();
var sessFT=Session.SessionFactory.OpenSession();
Task GetThingTask=新任务(()=>
{
fetchedThings=sessFT.CreateQuery(@“来自对象t”+
“内部连接获取t.BlueEntity”)
.SetResult变压器(变压器距离)
.List();
初始化(获取内容);
});
getThingTask.Start();
var fetchedYellows=新列表();
var sessFY=Session.SessionFactory.OpenSession();
任务getYellowsTask=新任务(()=>
{
fetchedYellows=sessFY.CreateQuery(@“来自Yellowy实体”+
“左连接获取y.SubYellowEntities”+…)
.SetResult变压器(变压器距离)
.List();
初始化(获取内容);
});
getYellowsTask.Start();
getThingsTask.Wait();
getYellowsTask.Wait();
Parallel.ForEach(fetchedThings,thing=>
{
thing.YELLOWEntities=fetchedYellows.Where(y=>y.thing.Id==thing.Id.ToList();
...
//…内部foreach()循环遍历“YELLOWthings”…执行线程安全的操作
...
});
//处理临时会话

感谢您的不同观点。我的例子过于简化了。有几个主要实体(包括集合等)将以大型数据集的形式返回。总的来说,Nhibernate需要27秒才能返回。处理数据还需要70秒。事实证明。在2个处理器上,运行时间减少了一半。我一定会跟进您关于会话的建议和警告。
session.Query().Where(conditions).ToList()
,并适当配置批大小以避免N+1。