2016-04-13 21 views
5

Mam listę kolekcjonerską BossList. W tym używam zagnieżdżonej. Any(), aby określić warunek. Teraz wydajność jest bardzo powolna w moim prawdziwym projekcie. Rozważ poniższy przykładowy kod źródłowy.Jak uniknąć kolejnych zagnieżdżonych. Każdy w C# LINQ

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(); 
} 

klasy modelu są

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; } 
} 

Głównego LINQ kwerendy jest

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

W moim głównym projektem, zawiera 6 zagnieżdżone .Any(). Tutaj nie mogę utworzyć z powodu długiego kodu.

Używam kwerendy w EF jako IQueryable. Baza danych zawiera ponad 1000K rekordów.

Proszę mi powiedzieć, czy istnieje jakiś skuteczny sposób na zmaksymalizowanie wydajności?

+1

Dzięki za kod LINQPad! Czy jest to uproszczona wersja zapytania EF? –

+0

@stuartd - Używam kwerendy w EF jako IQueryable. –

+0

@IvanStoev - Dodałem go w pytaniu. –

Odpowiedz

1

Prawdopodobnie najlepszym sposobem na to jest jeszcze za pomocą BossList jako punkt wyjścia, ale zbudować listę identyfikatorów, w którym powinno nastąpić ich identyfikatory:

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

W SQL to prawdopodobnie przełoży się zgrabny i wydajny EXISTS zapytanie.

Należy pamiętać, że zakładam, że w swoim prawdziwym modelu masz referencje zwrotne (PayrollInfos.Employee) i że użyłem elementu zastępczego BossId, który powinieneś zastąpić rzeczywistymi właściwościami klucza. Z twojego przykładu nie jest jasne, jak działają referencje ID i SID.

db to instancja DbContext.

Aby wyjaśnić to podejście nieco więcej: z mojego doświadczenia zazwyczaj najlepiej jest rozpocząć kwerendę z kolekcji, która zawiera wyniki, których szukasz, tj. Bosslist, a następnie dodać predykaty, które filtrują wyniki. Inne odpowiedzi zaczynają się od PayrollInfo. To jest w porządku, ale na koniec potrzebujesz grupowania lub Distinct, aby usunąć duplikaty. Zwykle nie powoduje to, że plan zapytania jest lepszy niż stosunkowo prosty table WHERE EXSIST(subqyery).

+0

Proszę, proszę, proszę. –

+0

Jestem nowy w tym LINQ. Proszę przedstawić swój kod szczególnie proszę PayrollInfos –

+0

Dodałem trochę wyjaśnień. –

1

Co się stanie, jeśli dodasz coś takiego jak klucz obcy do "rodzica" w każdej jednostce?

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

A kiedy można ustawić nową właściwość podczas tworzenia Person - parametr w konstruktorze:

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

Albo po prostu zdefiniować metodę, która ustawia PayInfo. Cokolwiek lubisz. A następnie zrób to samo dla osoby i szefa. A potem można napisać smth jak

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

Zakładając, że jest to rozwodnione zapytania EF; Chciałbym cofnąć Twój wybór, aby rozpocząć od PayrollInfo, a następnie wybrać nazwę szefa:

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();