2010-12-30 14 views
6

Mam klasy TaskWeekUI z tej definicji:LINQ- Max w którym warunek

public class TaskWeekUI { 
    public Guid TaskWeekId { get; set; } 
    public Guid TaskId { get; set; } 
    public Guid WeekId { get; set; } 
    public DateTime EndDate { get; set; } 
    public string PersianEndDate { get; set; } 
    public double PlanProgress { get; set; } 
    public double ActualProgress { get; set; } } 

i napisałem to zapytanie:

TaskWeekUI ti = tis.First(t => t.PlanProgress > 0 && t.EndDate == tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate)); 

Czy ta kwerenda jest prawdą? Czy mogę napisać moje zapytanie lepiej niż to?

+0

Przepraszam, edytowałem i dodałem zapytanie, zapomniałem. – Shayan

+0

'p => p.PlanProgress! = Null' nie jest wymagane w twoim' Where' klauzula – fearofawhackplanet

+0

Tnx, Ale czy mogę napisać zapytanie o max w którym stanie? – Shayan

Odpowiedz

26

Myślę, że chcesz tego, którego PlanProgress > 0 ma najnowsza EndDate.

TaskWeekUI ti = tis.Where(t => t.PlanProgress > 0) 
        .OrderByDescending(t => t.EndDate) 
        .FirstOrDefault(); 
+1

+1, ładne jasne rozwiązanie bez żadnych dodatkowych wyjątków wprowadzonych przy użyciu Max. – WileCau

+1

Tnx, myślę, że to najlepsze rozwiązanie. – Shayan

+2

Czy nie jest stratą czasu, aby posortować całą listę tylko po to, aby uzyskać pozycję o najwyższej wartości 'EndDate'? [This] (http://stackoverflow.com/a/1101979/1219414) wydaje się lepszym rozwiązaniem. – Juan

3

To zapytanie wydaje się poprawne z punktu widzenia uzyskanego wyniku.

Ale w swoim wewnętrznym zapytania tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate) jest obliczana dla każdego elementu w kolekcji z t.PlanProgress > 0

więc jego lepszym sposobem na uzyskanie maksymalnej wartości poza kwerendy następująco:

var max = tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate); 
tis.First(t => t.PlanProgress > 0 && t.EndDate == max); 

Idąc dalej str. PlanProgress! = Null jest zawsze prawdziwe, ponieważ p.PlanProgress nie ma typu Nullable. Więc nasz kod staje się tak:

var max = tis.Where(p => p.PlanProgress > 0).Max(w => w.EndDate); 
    tis.First(t => t.PlanProgress > 0 && t.EndDate == max); 

Albo można zmienić definicję klasy i uczynić p.PlanProgress typu pustych:

public class TaskWeekUI { 
    public Guid TaskWeekId { get; set; } 
    public Guid TaskId { get; set; } 
    public Guid WeekId { get; set; } 
    public DateTime EndDate { get; set; } 
    public string PersianEndDate { get; set; } 
    public double? PlanProgress { get; set; } 
    public double ActualProgress { get; set; }  
} 

var max = tis.Where(p => p.PlanProgress.HasValue && p.PlanProgress.Value > 0).Max(w => w.EndDate); 
    tis.First(t => t.PlanProgress.HasValue && t.PlanProgress.Value > 0 && t.EndDate == max); 
+1

+1, jedyne, co chciałbym zmienić, to "Pierwszy" do "FirstOrDefault", chyba że może zagwarantować, że zawsze znajdzie się element z 'PlanProgress> 0' –

+0

+1, ale myślę, że 'kolekcja .Max "zgłasza wyjątek, jeśli" kolekcja "jest pusta, więc prawdopodobnie konieczne będzie dodatkowe sprawdzenie przed ustawieniem" maksimum ". Kolekcja będzie pusta, jeśli cały PlanProgress <= 0. Ponieważ istnieją kontrole dla PlanProgress> 0 Zakładam, że PlanProgress <= 0 jest legalny i prawdopodobnie nie będzie oczekiwany wyjątek. – WileCau

+0

Tnx za odpowiedź. – Shayan

-1

Nie trzeba porównać PlanProgress NULL ponieważ podwójna jest typu struct, nie może mieć wartości NULL.

Jeśli chcesz TaskWeekUI z max EndDate i pozytywne PlanProgress Można spróbować tego kodu:

TaskWeekUI ti = tis.Where(t => t.PlanProgress > 0).Max(w => w.EndDate); 
+0

Kończy to przypisywanie 'DateTime' do' TaskWeekUI' – nan

+5

Nie można niejawnie przekonwertować typu "System.DateTime" na "TaskWeekUI" – Shayan