2010-10-29 2 views
1

У меня есть выражение LINQ, которое используется как файл в инструкции LINQ to SQL where where. Моя проблема в том, что выражение LINQ to SQL стало громоздким, а также содержащаяся в нем логика оказалась в нескольких местах, нарушающих DRY (это уже третий раз, когда я работаю над ошибкой, вызванной QA, поскольку она выходит из синхронизации).Консолидация или повторное использование выражения LINQ

Можно ли каким-либо образом повторно использовать выражение LINQ, подобное приведенному ниже, или разложить его на более мелкие подвыражения? Моя самая большая проблема заключается в том, что, поскольку выражение используется в вызове LINQ to SQL, оно не может использовать какие-либо другие классы или методы, поскольку библиотека LINQ to SQL не будет знать, как выразить их как 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); 
    } 
} 

В идеале, что бы я хотел сделать, это что-то вроде ниже. Это не работает, потому что LINQ to SQL не может выразить метод GetStatus(). Надеюсь, есть и другие умные способы сделать это?

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

ответ

1

Попробуйте что-то вроде следующего:

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

Вы можете 'переключатель (строка)' – abatishchev

+0

Я не думаю, что L2S может перевести 'switch' на SQL. –