データを同時に処理できるように、コレクションのコレクションなどを持つエンティティを積極的に取得する必要がありました (それぞれが多くの SubYellowEntities を持つ多くの YELLOWEntities を持つ Thing エンティティ)。必要なキーコードは次のとおりです。
NHibernateUtil.Initialize(fetchedThings);
(以下の受け入れられた回答を参照してください。)
データを同時に処理できるように、コレクションのコレクションなどを持つエンティティを積極的に取得する必要がありました (それぞれが多くの SubYellowEntities を持つ多くの YELLOWEntities を持つ Thing エンティティ)。必要なキーコードは次のとおりです。
NHibernateUtil.Initialize(fetchedThings);
(以下の受け入れられた回答を参照してください。)
解決策(これを改善できる場合は、先に進んで、答えとしてリビジョンを投稿してください): 8つのプロセッサで17秒(97から減少)で実行され、正しい結果が得られます。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
現在のアプローチにはいくつかの問題があります。問題を改めて見てみましょう。
あなたは、私が理解しているように、Things
多対1のを取得しようとしています。BlueEntities
また、のコレクションはYellowEntities
、のコレクションを持っていSubYellowEntities
ます。
、トランスフォーマーとループを使用する代わりに、エンティティとコレクションのバッチフェッチjoin fetch
を調べる必要があります。
、、に適切なバッチサイズを設定するとBlueEntity
、TPLのものはまったく必要ありません。Thing.YellowEntities
YellowEntity.SubYellowEntities
その場合、安全に使用できるエンティティを返すことはできません。これは、エンティティを有用なものにするために単一のセッションに関連付ける必要があり、セッションはスレッドセーフではないためです。