在LINQ到Entities Where表达式中如何构建逻辑提供的逻辑? [英] How can I build logic upon supplied logic in a LINQ-to-Entities Where expression?

查看:107
本文介绍了在LINQ到Entities Where表达式中如何构建逻辑提供的逻辑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常遇到LINQ for Entity Framework,一种模式,在这里我添加了一个。如果指定了一个字符串值,那么子句,如:

  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>其中,EqualIfSpecified< T>(
此IQueryable< T>查询,
表达式< Func< T,string>> fieldDelegate,
string filterValue)
{
返回字符串.IsNullOrWhiteSpace(filterValue)
?查询
:query.Where(x => fieldDelegate(x)== filterValue); //无效,请参阅下面的问题
}

所以我可以改变我的代码到:

  IQueryable&Foo> query = Foos.AsQueryable()
.WhereEqualIfSpecified(x => x.Name,nameFilter)
.WhereEqualIfSpecified(x => x.Address,addressFilter)
.WhereEqualIfSpecified(x = > x.City,cityFilter)
// ...
;但是我发现在 WhereEqualIfSpecified 中,上面的方法, fieldDelegate 必须被编译为一个 Func()被调用对实体源,这废止了点执行这些步骤,这将在我的原始代码中的数据库中执行。



我错过了如何创建新的来自 fieldDelegate 的表达式可以进行比较,而不仅仅是返回字符串值。这种方法是否有效?如何在 WhereEqualIfSpecified 中使必要的表达式允许LINQ到实体稍后执行?

解决方案

这里要做的是组合表达式。与代表不同,表达方式有点复杂。 这里是如何撰写表达式的一个实现。一旦你有这个 Compose 方法,你可以写你的扩展方法为:

  public static IQueryable< T> WhereEqualIfSpecified< T>(
this IQueryable< T>查询
表达式&FunC< T,string>> fieldExpression,
string filterValue)
{
返回字符串.IsNullOrWhiteSpace(filterValue)
?查询
:query.Where(fieldExpression.Compose(value => value == filterValue);
}


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?

解决方案

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

这篇关于在LINQ到Entities Where表达式中如何构建逻辑提供的逻辑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆