2016-11-15 33 views
0

我经常遇到,在LINQ的实体框架,在这里我添加了一个.Where子句如果指定一个字符串值,喜欢的模式:如何在LINQ-to-Entities Where表达式中根据提供的逻辑构建逻辑?

IQueryable<Foo> query = Foos.AsQueryable() 
if (!string.IsNullOrWhitespace(nameFilter)) query = query.Where(x => x.Name == name); 
if (!string.IsNullOrWhitespace(addressFilter) != null) query = query.Where(x => x.Address == addressFilter); 
if (!string.IsNullOrWhitespace(cityFilter) != null) query = query.Where(x => x.City == cityFilter); 
// ... 

我想打扫一下,避免重复过滤器。我以为我可以创建一个扩展方法:

public static IQueryable<T> WhereEqualIfSpecified<T>(
    this IQueryable<T> query, 
    Expression<Func<T, string>> fieldDelegate, 
    string filterValue) 
{ 
    return string.IsNullOrWhiteSpace(filterValue) 
     ? query 
     : query.Where(x => fieldDelegate(x) == filterValue); // not valid, see question below 
} 

所以,我可以代替更改我的代码:

IQueryable<Foo> query = Foos.AsQueryable() 
    .WhereEqualIfSpecified(x => x.Name, nameFilter) 
    .WhereEqualIfSpecified(x => x.Address, addressFilter) 
    .WhereEqualIfSpecified(x => x.City, cityFilter) 
    // ... 
; 

但是我发现,在上述WhereEqualIfSpecified方法,fieldDelegate必须被编译成一个Func()将针对实体源进行调用,这会破坏执行这些步骤的要点,这些步骤将在我的原始代码中的数据库中执行。

我错过了如何从fieldDelegate创建新的Expression的最后一步,它可以进行比较,而不仅仅是返回字符串值。这种方法会起作用吗?如何使WhereEqualIfSpecified中的Expression为允许LINQ-to-Entities稍后执行它?

回答

2

你在这里要做的是编写表达式。与代表不同,表达式有更多的构图技巧。 Here是如何编写表达式的一个实现。一旦你有这个Compose方法,你可以写你的扩展方法为:

public static IQueryable<T> WhereEqualIfSpecified<T>(
    this IQueryable<T> query, 
    Expression<Func<T, string>> fieldExpression, 
    string filterValue) 
{ 
    return string.IsNullOrWhiteSpace(filterValue) 
     ? query 
     : query.Where(fieldExpression.Compose(value => value == filterValue); 
} 
+0

谢谢!它的工作,我学到了很多关于表达式的工作。 –