How can I build logic upon supplied logic in a LINQ-to-Entities Where expression?

大憨熊 提交于 2020-05-28 12:05:12

问题


I often come across, in LINQ for Entity Framework, a pattern where I add a .Where clause if a string value is specified, like:

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 );
// ...

I wanted to clean this up and avoid repeating the filter. I thought I could create an extension method:

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
}

So that I can instead change my code to:

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

But I found that, in the WhereEqualIfSpecified method above, fieldDelegate must be compiled to a Func() to be invoked against the entity source, which ruins the point of doing these steps, which would be executed in the database in my original code.

I am missing the last step of how to create a new Expression from fieldDelegate that can do a comparison, rather than just returning the string value. Will this approach work? How do I make the necessary Expression in WhereEqualIfSpecified to allow LINQ-to-Entities to execute it later?


回答1:


What you're trying to do here is to compose expressions. Expressions, unlike delegates, are a bit tricker to compose. Here is one implementation of how to compose expressions. Once you have that Compose method you can write your extension method as:

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


来源:https://stackoverflow.com/questions/61972955/iqueryable-extension-method-with-dynamic-expression-passed-for-different-propert

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!