1

Nhibernateの将来のクエリを使用していくつかのデータを熱心に読み込もうとしています。 ToList()を呼び出す際に既に知っているように、これまでに行ったすべてのクエリは1つのトランザクションで実行されます。Nhibernate - パラメータ値の同じものが将来のさまざまなクエリに異なる名前で適用されます

var selectedPhysicianIds = new List<int> {1, 2}; 

var query = this.physicianReviewQuery.Clone() 
       .TransformUsing(new DistinctRootEntityResultTransformer()) 
       .AndRestrictionOn(p => p.Id) 
       .IsIn(selectedPhysicianIds) 
       .Future(); 

var collectionsQuery = this.session.QueryOver<Physician>() 
          .AndRestrictionOn(p => p.Id) 
          .IsIn(selectedPhysicianIds); 
collectionsQuery.Clone().Fetch(p => p.Specialties).Eager.Future(); 
collectionsQuery.Clone().Fetch(p => p.HospitalPhysicianBridges).Eager.Future(); 
collectionsQuery.Clone().Fetch(p => p.SpecialtyPhysicianBridges).Eager.Future(); 

selectedPhysicians.AddRange(query.ToList()); 

このコードは、SQLクエリに見ながら、パラメータ値の同じ数が異なるパラメータ名を持つすべてのクエリに適用され、クエリの組の下

Select * from PhysicianReview where PhysicianKey in (@p0, @p1) 

Select * from Physician P left outer join Specialties S on P.Specialty = S.Specialty 
Where P.PhysicianKey in (@p2, @p3) 

Select * from Physician P left outer join HospitalBridge HB on P.Physician = HB.Physician 
Where PhysicianKey in (@p4, @p5) 

Select * from Physician P left outer join SpecialtyBridge SB on P.Physican = SB.Physician 
Where PhysicianKey in (@p6, @p7) 
    ',N'@p0 int,@p1 int,@p2 int,@p3 int,@p4 int,@p5 int,@p6 int,@p7 int, 
    @p0=1,@p1=2,@p2=1,@p3=2,@p4=1,@p5=2,@p6=1,@p7=2 

を生成します。

たとえば、selectedPhysicianIdsには1000の整数の配列が含まれています(ユーザーは任意のものを選択できます)。

var selectedPhysicianIds = new List<int> {1, 2,....998, 999, 1000}; 

この場合、4つの将来のすべてのクエリに同じ数のパラメータ値が適用されます。したがって、パラメータの合計数は(4 * 1000)4000になります。ただし、SQL Serverには以下の制限があります。 "着信要求には多すぎるパラメータがあります。サーバは最大2100のパラメータをサポートしています"

Nhibernateの助けを借りてこの問題を解決するオプションはありますか?

答えて

0

いいえ、私はすでにあなたにコメントしてきたと信じていました。あなたの質問を削除して再投稿しましたか?これはかなり悪い行為になります。

将来の各クエリは、独自のパラメータセットを持つ異なるクエリとして扱われます。 NHibernateはそれらを "相互に"しようとしません、それはあまりにも複雑です。

これは、パラメータ数の上限に達するのを避けるために、クエリを分割することになります。最も簡単な方法:あなたのIDリストを分割し、次のセットを構築する前に、前のセットを解決して、将来のコールの多くのセットを実行します。

そうでなければ、熱心なフェッチを忘れて、遅延読み込みに固執します。 enabling batch loading of lazy loadsでN + 1個の選択問題を避けてください。これははるかに簡単です。セッションを閉じてエンティティを使用する必要がある場合は、遅延ロードされたプロパティでNHibernateUtil.Initialize()を呼び出し、エンティティをループして遅延ロードをトリガする必要があります。遅延ロードバッチのおかげで既にロードされているものでは何もしません。もう1つのオプションは、セッションを閉じる前にエンティティをビューモデルのようなものに変換することです。

関連する問題