2011-06-17 14 views
2

誰かが私に次のシナリオのlinqクエリを生成するのを手伝ってくれるのだろうかと思っていました。だから、基本的に、私はのためのボーナス計画にdirectreportsを得るためにこれを持ってLinqは、子リスト内のオブジェクトのプロパティで条件が満たされるリスト(親)内の要素を取得しますか?

IEnumerable<Employee> GetDirectReportsWithoutBonusPlansCreatedForFiscalPeriod(FiscalPeriod fiscalPeriod) 

:私はメソッドを作成しようとしている

public class Employee 
{ 
    IList<Employee> DirectReports { get; set;} 
    IList<BonusPlan> BonusPlans { get; set;} 

    BonusPlanTemplate BonusPlanTemplate { get; set;} 
} 

public class BonusPlan 
{ 
    FiscalPeriod FiscalPeriod { get; set; } 
    Employee Employee { get; set;} 
} 

:ここ

は、関連するプロパティを持つクラスです特定の会計期間:

var query = from dr in DirectReports 
      from bp in dr.BonusPlans 
      where bp.Employee.BonusPlanTemplate != BonusPlanTemplate.Empty && 
       bp.FiscalPeriod==fiscalPeriod 
      select dr; 

IList<Employee> directReportsWithBonusPlansCreated = query.ToList(); 

次に、すべてのDirectReportsにbonu (BonusPlanTemplateが割り当てられていることによって示された)プランのセットアップが、前のクエリのリストにない場合。

var query2 = from dr in DirectReports 
      where dr.BonusPlanTemplate != BonusPlanTemplate.Empty && 
       !directReportsWithBonusPlansCreated.Contains(dr) 
      select dr; 

これは正しい結果をもたらしますが、別の方法が必要なようです。私は2つのステップでこれを行う必要があるかどうかはわかりません。誰かが私はこれらの2つのlinqクエリを組み合わせて、おそらくそれをより効率的にする助けてもらえますか?私はLinqの経験が比較的少ないです。

+0

直接レポートに1つの期間に複数のボーナスプランがある場合、最初のクエリで重複が返されます...それは慎重ですか? –

+0

このコメントをありがとうございます。将来的には、一度に「作成済み」のステータスを持つ従業員に対して1つのボーナスプランしか存在しないステータスフィールドがあります。しかし、あなたは正しい。それはそのまま、私は重複を取得します。 – SideFX

答えて

3

その他の理由で最初のクエリが必要ですか?そうでない場合、それは非常に簡単です:

public bool HasBonusPlanForPeriod(FiscalPeriod period) 
{ 
    return BonusPlans.Any(bp => bp.FiscalPeriod == fiscalPeriod); 
} 

を次に、あなたのオリジナルの最初のクエリは次のようになります:

var query = from dr in DirectReports 
      where dr.BonusPlanTemplate != BonusPlanTemplate.Empty && 
        dr.HasBonusPlanForPeriod(fiscalPeriod) 
      select dr; 

IList<Employee> directReportsWithBonusPlansCreated = query.ToList(); 

var query = from dr in DirectReports 
      where dr.BonusPlanTemplate != BonusPlanTemplate.Empty 
       && !dr.BonusPlans.Any(bp => bp.FiscalPeriod == fiscalPeriod) 
      select dr; 

あなたはEmployeeに余分なメソッドを使用し簡単にあなたの人生を作ることができます2番目のクエリは次のようになります。

var query = from dr in DirectReports 
      where dr.BonusPlanTemplate != BonusPlanTemplate.Empty && 
        !dr.HasBonusPlanForPeriod(fiscalPeriod) 
      select dr; 

IList<Employee> directReportsWithBonusPlansCreated = query.ToList(); 
+0

私は本当に、Linqの "等しくない"展開を行う方法の知識が不足しているため、減算を行う以外の最初のクエリは必要ありませんでした。あなたの解決策は、私の単体テストを通過させます。ありがとうジョン! – SideFX

+2

@SideFX:ユニットテストを開始するための+1。 –

1

これはトリッキーなものです...まず、「ああ、それは外部結合です... Use DefaultIfEmpty」です。それから、私はあなたが選択した多くのことをしていることに気付きました(それが2つの句から始まります)。そこで、SelectManyとcame up with this gemを組み合わせてDefaultIfEmptyを検索しました。あなたのシナリオに適用されます

var query = 
    from dr in DirectReports    
    from bp in dr.BonusPlans.DefaultIfEmpty() 

    where dr.BonusPlanTemplate != BonusPlanTemplate.Empty && 
    bp.FiscalPeriod==fiscalPeriod && 
    bp==null 
    select dr; 

これが機能するかどうかを確認してください。

関連する問題