2010-10-29 11 views
1

J'ai une expression LINQ qui est utilisée comme un fichier dans une instruction LINQ to SQL où clause. Mon problème est que l'expression LINQ to SQL est devenue lourde et que la logique qu'elle contient s'est retrouvée dans plusieurs endroits violant DRY (c'est la 3ème fois que je travaille sur un bug soulevé par QA pour qu'il ne soit plus synchronisé).Consolider ou réutiliser l'expression LINQ

Est-il possible de réutiliser une expression LINQ comme celle ci-dessous ou de la décomposer en sous-expressions plus petites? Mon plus gros problème est que parce que l'expression est utilisée dans un appel LINQ to SQL, elle ne peut pas utiliser d'autres classes ou méthodes car la bibliothèque LINQ to SQL ne sait pas comment les exprimer en SQL.

public static Expression<Func<MyClass, bool>> MyClassFilterExpression 
{ 
    get 
    { 
     return x => (x.Status.Count > 0 && x.Status.Any(y => y.StatusID == 5)) ? "Refused" : 
      (x.Status.Count > 0 && x.Status.Any(y => y.StatusID == 6)) ? "Cancelled" : 
       (x.DateTimeExpired.HasValue && DateTime.Today > x.DateTimeExpired.Value) ? "Expired" : 
        (x.Duration.HasValue && x.DurationTypeID.HasValue && x.DateTimeApproved.HasValue) ? 
         (x.DurationTypeID == (int)DurationTypes.Day && DateTime.Today > x.DateTimeApproved.Value.AddDays(x.Duration.Value)) ? "Expired" : 
          (x.Status.Count > 0 && x.Status.Any(y => y.StatusID == 4 || y.StatusID == 10)) ? "Approved" : "Pending").Contains(filterValue); 
    } 
} 

Idéalement ce que je voudrais être en mesure de faire est quelque chose comme ci-dessous. Cela ne fonctionne pas car LINQ to SQL ne peut pas exprimer la méthode GetStatus(). Espérons qu'il existe une autre façon intelligente de le faire?

public ReviewStatuses GetStatus(DateTime? dateTimeExpired, int? reviewStatusID) 
{ 
    var isExpired = (dateTimeExpired.HasValue && DateTime.Today >= dateTimeExpired.Value.Date); 

    if (reviewStatusID == ReviewStatuses.Cancelled.GetHashCode()) 
    { 
     return ReviewStatuses.Cancelled; 
    } 
    else if (reviewStatusID == ReviewStatuses.Refused.GetHashCode()) 
    { 
     return ReviewStatuses.Refused; 
    } 
    return ReviewStatuses.Pending; 
} 

public static Expression<Func<MyClass, bool>> MyClassFilterExpression 
{ 
    get 
    { 
     return x => x.Status.Count > 0 && x.Status.Any(y => GetStatus(y.DateTimeExpired, y.StatusID)).Contains(filterValue); 
    } 
} 

Répondre

1

Essayez quelque chose comme ce qui suit:

public static Expression<Func<MyClass, bool>> GetMyClassFilterExpression(string filterValue) { 

    if (filterValue == "Refused") 
    return x => (x.Status.Count > 0 && x.Status.Any(y => y.StatusID == 5)); 
    else if (filterValue == "Cancelled") 
    return x => (x.Status.Count > 0 && x.Status.Any(y => y.StatusID == 6)); 
    else if (filterValue == "Expired") 
    return x => (x.DateTimeExpired.HasValue && DateTime.Today > x.DateTimeExpired.Value) || 
     (x.DurationTypeID == (int)DurationTypes.Day && DateTime.Today > x.DateTimeApproved.Value.AddDays(x.Duration.Value)); 
    else if (filterValue == "Approved") 
    return x => (x.Status.Count > 0 && x.Status.Any(y => y.StatusID == 4 || y.StatusID == 10)); 
    // and so on... 
    else 
    throw new ArgumentException("Your message."); 
} 

.... 

string filterValue = "Refused"; 
Expression<Func<MyClass, bool>> whereCluase = GetMyClassFilterExpression(filterValue); 
var list = dataContext.MyClasses.Where(whereCluase).ToList(); 
+0

Vous pouvez 'interrupteur (string)' – abatishchev

+0

Je ne pense pas que L2S peut traduire un 'switch' à SQL. –