2016-04-13 5 views
5

私はコレクションリストBossListを持っています。その中で、条件を決定するためにネストされた.Any()を使用しています。今はパフォーマンスが私の実際のプロジェクトでは非常に遅いです。次のサンプルソースコードを検討してください。C#LINQで連続してネストされた.Anyを避ける方法

void Main() 
{ 

    List<Boss> BossList = new List<Boss>() 
    { 
     new Boss() 
     { 
      ID = 101, 
      Name = "Harry", 
      Department = "Development", 
      Gender = "Male", 
      Role = "Manager", 
      Employees = new List<Person>() { 
       new Person() { 
        ID = 101, 
        SID = 102, 
        Name = "Peter", 
        Department = "Development", 
        Gender = "Male", 
        Role = "Assistant", 
        PayInfo = new List<PayrollInfo>() 
        { 
         new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6 }, 
         new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2 }, 
         new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6 }, 
         new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8 }, 
         new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9 }, 
         new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 }, 
        } 
       }, 
       new Person() { 
        ID = 101, 
        SID = 103, 
        Name = "Emma Watson", 
        Department = "Development", 
        Gender = "Female", 
        Role = "Assistant", 
        PayInfo = new List<PayrollInfo>() { 
         new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 5 }, 
         new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 9 }, 
         new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 2 }, 
         new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 }, 
        } 
       }, 

      } 
     }, 
     new Boss() 
     { 
      ID = 104, 
      Name = "Raj", 
      Department = "Development", 
      Gender = "Male", 
      Role = "Manager", 
      Employees = new List<Person>() 
      { 
       new Person() { 
        ID = 104, 
        SID = 105, 
        Name = "Kaliya", 
        Department = "Development", 
        Gender = "Male", 
        Role = "Assistant", 
        PayInfo = new List<PayrollInfo>() { 
         new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6 }, 
         new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2 }, 
         new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6 }, 
         new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8 }, 
         new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9 }, 
         new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 }, 
        } 
       }, 
       new Person() { 
        ID = 104, 
        SID = 103, 
        Name = "Emma Watson", 
        Department = "Development", 
        Gender = "Female", 
        Role = "Assistant", 
        PayInfo = new List<PayrollInfo>() { 
         new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 5 }, 
         new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 9 }, 
         new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 2 }, 
         new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 }, 
        } 
       }, 

      }, 
     }, 
     new Boss() 
     { 
      ID = 102, 
      Name = "Peter", 
      Department = "Development", 
      Gender = "Male", 
      Role = "Manager", 
      Employees = new List<Person>() 
      { 
       new Person() { 
        ID = 102, 
        SID = 105, 
        Name = "Kaliya", 
        Department = "Development", 
        Gender = "Male", 
        Role = "Assistant", 
        PayInfo = new List<PayrollInfo>() { 
         new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6 }, 
         new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2 }, 
         new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6 }, 
         new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8 }, 
         new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9 }, 
         new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 }, 
        } 
       }, 
       new Person() { 
        ID = 102, 
        SID = 103, 
        Name = "Emma Watson", 
        Department = "Development", 
        Gender = "Female", 
        Role = "Assistant", 
        PayInfo = new List<PayrollInfo>() { 
         new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 5 }, 
         new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 9 }, 
         new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4 }, 
         new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3 }, 
         new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 2 }, 
         new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 1 }, 
         new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1 }, 
        } 
       } 
      } 
     } 
    }; 

    BossList.Where(i => i.Employees.Any(j => j.PayInfo.Any(s => s.AbsentDays >6))).Select(m => m.Name).Dump(); 
} 

モデル・クラスが

public class Person 
{ 
    public int ID { get; set; } 
    public int SID { get; set; } 
    public string Name { get; set; } 
    public string Department { get; set; } 
    public string Gender { get; set; } 
    public string Role { get; set; } 
    public List<PayrollInfo> PayInfo { get; set; } 
} 

public class Boss 
{ 
    public int ID { get; set; } 
    public int SID { get; set; } 
    public string Name { get; set; } 
    public string Department { get; set; } 
    public string Gender { get; set; } 
    public string Role { get; set; } 
    public List<Person> Employees { get; set; } 
} 

public class PayrollInfo 
{ 
    public int Monthof2015 { get; set; } 
    public int NetWorkingDays { get; set; } 
    public int AbsentDays { get; set; } 
} 

いる主なLINQクエリは、私のメインのプロジェクトで

BossList.Where(i => i.Employees 
         .Any(j => j.PayInfo 
           .Any(s => s.AbsentDays >6))) 
     .Select(m => m.Name); 

あり、それは)6ネストされた.ANYを(含まれています。ここで私は長いコードのために作成することができません。

私はEFでIQueryableとしてクエリを使用しています。データベースには1000,000以上のレコードが含まれています。

パフォーマンスを最大限に高める効率的な方法はありますか?

+1

ありがとうLINQPadコード!これはEFクエリの簡略版ですか? –

+0

@stuartd - EFでクエリをIQueryableとして使用しています。 –

+0

@ IvanStoev - 質問に追加しました。 –

答えて

1

おそらくこれを行うための最善の方法は、まだ出発点としてBossListを使用しますが、そのIDが発生しているIDのリストを構築している:SQLで

db.BossList.Where(b => db.PayrollInfos.Where(s => s.AbsentDays >6) 
           .Select(p => p.Employee.BossId) 
        .Contains(b.BossId)); 

これはおそらくきちんとして効率的に変換されますEXISTSクエリ。

実際のモデルでは、逆参照(PayrollInfos.Employee)があり、プレースホルダーBossIdを使用して、実際のキープロパティで置き換える必要があることに注意してください。あなたの例から、参考文献IDSIDの仕組みは少し不明です。

dbは、DbContextインスタンスです。

このアプローチをもう少し説明してください:私の経験では、通常、後で結果を含むコレクション、つまりBosslistでクエリを開始し、結果をフィルタリングする述語を追加するのが最も効果的です。その他の回答はPayrollInfoで始まります。それは問題ありませんが、最終的には重複を削除するにはグループ化するかDistinctが必要です。通常、これはクエリプランを比較的簡単なtable WHERE EXSIST(subqyery)よりも良くするものではありません。

+0

あなたはそれを詳しく教えてもらえますか? –

+0

このLINQの新機能です。 PayrollInfos –

+0

私はいくつかの説明を追加しました。 –

1

各エンティティで「親」に外部キーのようなものを追加するとどうなりますか?

public class PayrollInfo 
{ 
    public int Monthof2015 { get; set; } 
    public int NetWorkingDays { get; set; } 
    public int AbsentDays { get; set; } 
    public Person Person { get; set; } 
} 

、いつPersonを作成中に新しいプロパティを設定することができます - コンストラクタ内のパラメータ:

public Person(IList<PayrollInfo> list) 
{ 
    this.PayInfo = list; 
    foreach(var pay in this.PayInfo) 
     pay.Person = this; 
} 

それともPayInfoを設定する方法を定義します。君が好きなものならなんでも。 そしてPersonとBossについても同じことをしてください。 そして、あなたは、これが骨抜きEFクエリであると仮定すると、

AllPayrollInfos.Where(x => x.Days > 6).GroupBy(x => x.Person.Boss).Select(x => x.Key).ToList(); 
1

のようになめらかに書くことができます。私はあなたの選択をPayrollInfoから開始し、次にBossの名前を選択して戻します:

Boss Boss = new Boss 
{ 
    ID = 101, 
    Name = "Harry", 
    Department = "Development", 
    Gender = "Male", 
    Role = "Manager", 
}; 
Person Person = new Person() { ID = 101, SID = 102, Name = "Peter", Department = "Development", Gender = "Male", Role = "Assistant", Boss = Boss}; 
List<PayrollInfo> PayrollInfoList = new List<UserQuery.PayrollInfo> 
{ 
    new PayrollInfo() { Monthof2015 = 1, NetWorkingDays = 24, AbsentDays = 6, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 2, NetWorkingDays = 23, AbsentDays = 3, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 3, NetWorkingDays = 20, AbsentDays = 2, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 4, NetWorkingDays = 22, AbsentDays = 1, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 5, NetWorkingDays = 24, AbsentDays = 4, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 6, NetWorkingDays = 26, AbsentDays = 6, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 7, NetWorkingDays = 25, AbsentDays = 4, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 8, NetWorkingDays = 21, AbsentDays = 3, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 9, NetWorkingDays = 20, AbsentDays = 8, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 10, NetWorkingDays = 25, AbsentDays = 9, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 11, NetWorkingDays = 24, AbsentDays = 4, Person = Person }, 
    new PayrollInfo() { Monthof2015 = 12, NetWorkingDays = 26, AbsentDays = 1, Person = Person }, 
}; 


PayrollInfoList.Where(p => p.AbsentDays > 6).Select(p => p.Person.Boss.Name).Distinct().Dump(); 
関連する問題