2012-02-14 3 views
1

でのLINQを使用するときに参加する基本的に、私は重複につながるこのlinq-to-nhibernate-produces-unnecessary-joins重複や不要なNHibernateは

List<Competitions> dtoCompetitions; 
dtoCompetitions = (from compset in session.Query<FWBCompetitionSet>() 
        where compset.HeadLine == true 
        && compset.A.B.CurrentSeason == true 
        select (new Competitions 
          { 
             CompetitionSetID = compset.CompetitionSetID, 
             Name = compset.Name, 
             Description = compset.Description, 
             Area = compset.Area, 
             Type = compset.Type, 
             CurrentSeason = compset.A.B.CurrentSeason, 
             StartDate = compset.StartDate 
          } 
        )).ToList(); 

でのLINQプロバイダの同じ問題を渡ったが、これらが結合して生成されたSQL

SELECT fwbcompeti0_.competitionsetid AS col_0_0_, 
    fwbcompeti0_.name    AS col_1_0_, 
    fwbcompeti0_.DESCRIPTION  AS col_2_0_, 
    fwbcompeti0_.area    AS col_3_0_, 
    fwbcompeti0_.TYPE    AS col_4_0_, 
    fwbseason3_.currentseason  AS col_5_0_, 
    fwbcompeti0_.startdate  AS col_6_0_ 
FROM fwbcompetitionset fwbcompeti0_ 
     INNER JOIN A fwbcompeti1_ 
     ON fwbcompeti0_.competitionseasonid = fwbcompeti1_.competitionseasonid 
     INNER JOIN A fwbcompeti2_ 
     ON fwbcompeti0_.competitionseasonid = fwbcompeti2_.competitionseasonid 
     INNER JOIN B fwbseason3_ 
     ON fwbcompeti2_.seasonid = fwbseason3_.seasonid 
WHERE fwbcompeti0_.headline = @p0 
     AND fwbseason3_.currentseason = @p1 

お知らせに参加しますこれらは完全に複製され、SQL Serverのパフォーマンスにも影響します。 NHibernateは3.2にアップデート1

 INNER JOIN A fwbcompeti1_ 
     ON fwbcompeti0_.competitionseasonid = fwbcompeti1_.competitionseasonid 
     INNER JOIN A fwbcompeti2_ 
     ON fwbcompeti0_.competitionseasonid = fwbcompeti2_.competitionseasonid 

は、このLINQのバグはまだ有効である、と私はシンプルかつ合理的なLINQのソリューションを見つけることができませんでした。 私はQueryOver + JoinAlias + TransformUsingを使って仕事を終えました。

FWBCompetitionSet compset = null; 
FWBCompetitionSeason compseason = null; 
FWBSeason season = null; 
IList<Competitions> dtoCompetitions; 
dtoCompetitions = session.QueryOver<FWBCompetitionSet>(() => compset) 
.JoinAlias(() => compset.FWBCompetitionSeason,() => compseason) 
.JoinAlias(() => compseason.FWBSeason,() => season) 
.Where(() => compset.HeadLine == true) 
.And(() => season.CurrentSeason == true) 
.SelectList(
list => list 
.Select(c => c.CompetitionSetID).WithAlias(() => compset.CompetitionSetID) 
.Select(c => c.Name).WithAlias(() => compset.Name) 
.Select(c => c.Description).WithAlias(() => compset.Description) 
.Select(c => c.Area).WithAlias(() => compset.Area) 
.Select(c => c.Type).WithAlias(() => compset.Type) 
.Select(c => season.CurrentSeason).WithAlias(() => season.CurrentSeason) 
.Select(c => c.StartDate).WithAlias(() => compset.StartDate) 
) 
.TransformUsing(Transformers.AliasToBean<Competitions>()) 
.List<Competitions>(); 

答えて

3

もう一つの編集:

私は私が最終的に何が起こっているのが分かったと思います。 LINQ to Hibernateプロバイダは、ターゲットからソーステーブルへの関連付けをナビゲートするのに問題があり、そのような関連に出会うたびに別々の結合を生成するようです。

マッピングを指定していないため、linq-to-nhibernate-produces-unnecessary-joinsからマッピングを使用しました。このモデルは文書と1つのジョブと多くのTranslationUnitsを持っています。各TranslationUnitには、翻訳エンティティが多数あります。

ジョブに基づいて変換を検索しようとすると、逆の順序で関連付けをトラバースし、LINQプロバイダはTranslation-> TranslationUnitとTranslationUnit to Documentの複数の結合を生成します。

このクエリでは、冗長生成します加わり:

session.Query<TmTranslation>() 
      .Where(x => x.TranslationUnit.Document.Job == job) 
      .OrderBy(x => x.Id) 
      .ToList(); 

あなたがドキュメントにナビゲーション順序を逆にした場合 - > TranslationUnit - >翻訳、あなたが発生しないクエリを取得する任意の冗長が加わり:

var items=(from doc in session.Query<Document>() 
     from tu in doc.TranslationUnits 
      from translation in tu.Translations 
     where doc.Job ==job       
     orderby translation.Id 
     select translation).ToList(); 

このような奇妙な点を考えると、QueryOverは優れた選択肢のようです。

前編集:

私は犯人がcompset.A.B.CurrentSeasonである疑いがあります。最初の結合されたテーブル(fwbcompeti1_)はA .Bを返しますが、次の2つ(fwbcompeti2_とfwbseason3_)はAを返します。B。 LINQ to NHibernateプロバイダは、Aがどこにも使用されておらず、生成された文からAを削除できないと推測しているようには見えません。

CurrentSeason = compset.A.Bを置き換えることによって、オプティマイザを少し助けてください。CurrentSeasonCurrentSeason = trueから選択、whereステートメントはCurrentSeason == trueの項目のみを返します。

EDIT:私は何を意味することは、このようなクエリを変更することです:

List<Competitions> dtoCompetitions; 
dtoCompetitions = (from compset in session.Query<FWBCompetitionSet>() 
        where compset.HeadLine == true 
        && compset.A.B.CurrentSeason == true 
        select (new Competitions 
         { 
            CompetitionSetID = compset.CompetitionSetID, 
            Name = compset.Name, 
            Description = compset.Description, 
            Area = compset.Area, 
            Type = compset.Type, 
            CurrentSeason = true, 
            StartDate = compset.StartDate 
         } 
       )).ToList(); 

私は単に真

+0

で値compset.A.B.CurrentSeasonを交換する。しかし、それはperformenceの問題を紹介します。あなたが最初に必要とする画像は、現在のシーズンの2行のデータを返す必要があります。代替ソリューション(CurrentSeason = true)を使用すると、システムは100行のデータを返します。 – ValidfroM

+0

選択部分の特定のフィールドに対して返す値の変更返される行の数を変更します。どういう意味ですか? –

+0

Panagiotisありがとう、今私はあなたのポイントを持って、それを試してみました。 Unfournately、それは同じSQLを与えた。 QueryOver APIに切り替える必要があると思う。 – ValidfroM

関連する問題