2010-12-01 8 views
0

質問:すべての子コレクションがfetchmode = eagerに設定されているルートエンティティでページングされた結果を返すように、熱心なロード基準を取得する方法。fetchmodeがeagerのNHibernateページング基準。 (流暢なNHを使用して)

私は、熱心に読み込まれた子コレクションを持つ10項目のページング結果セットを取得しようとしています。問題は、クエリが選択全体を囲む選択トップ10を実行することです。これにより、結合されたすべてのレコードを含む最初の10個の結果のみが返されます。最初のエンティティに10個の子オブジェクトがある場合、結果セットは10個の子オブジェクトがロードされた1個のエンティティを返します。私は水分補給されたエンティティと子コレクションが必要です(怠け者)。遅延ロードをオフにしてこのクエリを実行すると、結果セット内の各アソシエートに対してn + 1のクエリが取得されます。

これが私の基本的なクエリの処理です:

criteria = context.Session.CreateCriteria<Associate>(); 
criteria.SetMaxResults(10); //hardcoded for testing 
criteria.SetFirstResult(1); //hardcoded for testing 
criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
return criteria.List<Associate>(); 


public AssociateMap() 
    { 
     ReadOnly(); 
     Id(x => x.AssociateId); 
     Map(x => x.FirstName); 
     Map(x => x.LastName); 
     Map(x => x.ManagerId); 
     Map(x => x.Department); 
     Map(x => x.Email); 
     Map(x => x.JobTitle); 

     Map(x => x.LastFirstName).Formula("LTRIM(RTRIM(LastName)) + ', ' + LTRIM(RTRIM(FirstName))"); 

     HasMany(x => x.Messages).KeyColumn("AssociateId").Inverse().Cascade.All(); 
     HasMany(x => x.Roles).Element("RoleKey"); 
     HasMany(x => x.DirectReports).KeyColumn("ManagerId").Cascade.None().ForeignKeyConstraintName("FK_Associate_Manager"); 
     //HasMany(x => x.DirectReports).Element("ManagerId").CollectionType(typeof(Domain.Associate)); 


    } 

答えて

3

ソリューションは、最大の結果を設定するには、サブクエリを使用して終了しました。 Subqueries.PropertyInを使用してサブクエリを追加しました。私は、 "criterion expression"を図示していないコードに追加したので、 "criteria"を "limiter"にクローニングしています。したがって、これらの基準をサブクエリにクローンして、トップ10の選択を "IN"ステートメントに入れる必要があります。今度は子コレクションを読み込み、ルートエンティティにページネーションを追加して、デカルトやn + 1で問題なく10人のエンティティを返すことができます。私はより完全で組織的なコードをフォローアップしようとします。

//criteria = context.Session.CreateCriteria<Associate>(); 
//changed criteria to DetachedCriteria. 
criteria = DetachedCriteria.For<Associate>(); 

DetachedCriteria limiter = CriteriaTransformer.Clone(criteria); 
limiter.SetProjection(Projections.Id()); 
limiter.SetMaxResults(10); 
criteria.Add(Subqueries.PropertyIn("AssociateId", limiter)); 

criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
return criteria.List<Associate>(); 
+0

私はこの解決策が好きです。 –

+0

+1は答えを共有します。 – kerzek

関連する問題