我有一个LINQ表达式,它在LINQ to SQL语句where子句中用作文件管理器。我的问题是LINQ to SQL表达式变得笨拙,而且它所包含的逻辑最终导致了多个违反DRY的位置(这是我第三次处理QA因为它不同步而引发的错误)。
有没有什么办法可以重用下面的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);
}
}
答案 0 :(得分: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();