2010-12-30 24 views
6

Tengo una TaskWeekUI clase con esta definición:LINQ- Max en donde la condición

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

y escribí esta consulta:

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

¿Es esta consulta es cierto? ¿Puedo escribir mi consulta mejor que esto?

+0

discúlpeme, edité y agregué la consulta, lo olvidé. – Shayan

+0

'p => p.PlanProgress! = Null' no es necesario en la cláusula' Where' – fearofawhackplanet

+0

Tnx, pero ¿puedo escribir una consulta para max en dónde condición? – Shayan

Respuesta

26

Creo que desea que el uno cuya PlanProgress > 0 tiene un EndDate más reciente.

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

+1, una solución clara y agradable sin excepciones extrañas introducidas al usar Max. – WileCau

+1

Tnx, creo que es la mejor solución simple. – Shayan

+2

¿No es una pérdida de tiempo ordenar toda la lista solo para obtener el artículo con el mayor 'EndDate'? [Este] (http://stackoverflow.com/a/1101979/1219414) parece ser una mejor solución. – Juan

3

Esta consulta parece ser correcta desde el punto de vista del resultado obtenido.

Pero en su consulta interna tis.Where(p => p.PlanProgress != null && p.PlanProgress > 0).Max(w => w.EndDate) se calcula para cada elemento de colección con t.PlanProgress > 0

Así que es una mejor manera de obtener el valor máximo fuera de una consulta de la siguiente manera:

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

Yendo más lejos p. PlanProgress! = Null es siempre cierto, ya que p.PlanProgress no es de tipo Nullable. Así que nuestro código se convierte de esta manera:

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

o puede cambiar una definición de la clase y hacer p.PlanProgress de tipo anulable:

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, lo único que cambiaría es el 'First' a un' FirstOrDefault' a menos que pueda garantizar que siempre habrá un elemento con 'PlanProgress> 0' –

+0

+1, pero creo que 'colección .Max 'arroja una excepción si' colección 'está vacía, por lo que probablemente deba haber una verificación adicional antes de establecer' max '. La colección estará vacía si todo PlanProgress es <= 0. Dado que hay controles para PlanProgress> 0, supongo que PlanProgress <= 0 es legal y probablemente no se espere una excepción. – WileCau

+0

Tnx por su respuesta. – Shayan

-1

No es necesario comparar con PlanProgress nulo por doble es tipo de estructura, no puede ser nulo.

Si desea TaskWeekUI con Max y EndDate PlanProgress positivo Puede probar este código:

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

Terminará asignando 'DateTime' a' TaskWeekUI' – nan

+5

No se puede convertir implícitamente el tipo 'System.DateTime' a 'TaskWeekUI' – Shayan