1

LINQ で、どの WHERE 句がヒットしたかを確認する方法はありますか? Company というオブジェクトがあります。これは複数の BillTo オブジェクトを持つことができ、各 BillTo オブジェクトは複数の Generator オブジェクトを持つことができます。

Company
|
+-- BillTo1 - named First
|    |
|    |-- Generator1 - named Alpha
|    |
|    +-- Generator2 - named Beta
|
+-- BillTo2 - named Second
     |
     +-- Generator3 - name Gamma

これがlinqステートメントです(他のwhereステートメントの余分なものを取り除きました):

bool HaveCompany = !string.IsNullOrWhiteSpace(Company);
var AllData = (from co in db.Companies
             join bt in db.Billtoes on co.ID equals bt.CompanyID into bts
             from b in bts.DefaultIfEmpty()
             join gn in db.Generators on b.ID equals gn.BillToID into gns
             from g in gns.DefaultIfEmpty()
             where co.Active == true
             && (
                co.Name.Contains(HaveCompany ? Company : co.Name) ||
                b.Name.Contains(HaveCompany ? Company : b.Name) ||
                g.Name.Contains(HaveCompany ? Company : g.Name)
             )
             select new {
                 CompanyID = co.ID,
                 BillTo = b,
                 Generator = g,
                 Name = co.Name,
             }).ToList();

問題は、すべてが正しく検出されることです。BillTo で「名前」の一致が見つかった場合、「Generator = g」を実行する必要はありません。逆もまた同様で、Generator で一致する場合は、「BillTo = b」を実行する必要はありません。

したがって、どの WHERE 句がヒットしたかを知る方法があれば、適切な b または g を結果に追加します。結果を取得した後、WHERE 句として実際に送信している 7 つのフィールドのそれぞれを再確認した後、繰り返し実行できることはわかっていますが、余分なコードが多すぎるようです。おそらく私のLINQの微調整は順調ですか?何がヒットしたかを調べるために、リフレクションまたは何かを介して抽出できる値はありますか?

4

2 に答える 2

3

決定する必要があります-3 つの select ブランチが必要ですか (実際には、2 つのネストされた?:ステートメントになると思います)。それとも、すべての潜在的なメンバーを持つ 1 つのオブジェクトを選択しますか? 個人的には、ステートメントで具象型を使用する必要を避けるためにselect、またはdynamicI を使用して匿名型を展開するだけです。

を使用letしてContainsチェックを 1 回だけ実行し、where句と匿名型のメンバーの割り当ての両方でそれらを使用できます。

 /* .... */
 let coContains = co.Name.Contains(HaveCompany ? Company : co.Name)
 let bContains = b.Name.Contains(HaveCompany ? Company : b.Name)
 let gContains = g.Name.Contains(HaveCompany ? Company : g.Name)
 where co.Active == true
 && ( coContains || bContains || gContains )
 select new {
   /* sticking the booleans on there as well - might not want to do that */
   CoContains = coContains,
   BContains = bContains,
   GContains = gContains,
   /* other properties as per your code example */
   CompanyID = co.ID,
   BillTo = !gContains && bContains ? b : (BillTo)null,
   Generator = gContains && !bContains ? g : (Generator)null,
   Name = co.Name
 }).ToList();

したがって、あなたはまだ同じデータを返しています(コメントは、実際にはこれらの余分なブール値が必要ないかもしれないと言っているので、後で実行する制御フローロジックを簡素化する可能性があるため、そこに入れただけです)しかし、割り当てているだけですブール値が一致する場合(私が思うに)あなたの基準。BillToおよびGeneratorプロパティは、null読み取られるべきでない場合 (ここでは型名を想定しています) になります。

于 2012-05-01T20:57:03.553 に答える
0

どの基準が満たされているかを見極める場合は、データをフィルタリングするのではなく、データを分割している可能性があります。パーティショニングはGroupByの仕事です。次に、キーに基づいて条件付きグループ投影を実行できます。

.GroupBy(x =>  x.co.Name.Contains(HaveCompany ? Company : co.Name)  ? 1 :
  x.b.Name.Contains(HaveCompany ? Company : b.Name) ? 2 :
  x.gen.Name.Contains(HaveCompany ? Company : gen.Name) ? 3 :
  0
)
.SelectMany(g =>
g.Key == 1 ? g.Select(x => new {
  CompanyID = x.co.ID,
  BillTo = x.b,
  Generator = x.gen,
  Name = co.Name
} :
g.Key == 2 ? g.Select(x => new {
  CompanyID = co.ID,
  BillTo = b,
  Generator = (Generator) null,
  Name = co.Name
} :
g.Key == 3 ? g.Select(x => new {
  CompanyID = co.ID,
  BillTo = (BillTo) null,
  Generator = gen,
  Name = co.Name
} :
g.Where(x => false)
)
于 2012-05-02T14:20:34.350 に答える