首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >LINQ表达式中的String.IsNullOrWhiteSpace

LINQ表达式中的String.IsNullOrWhiteSpace
EN

Stack Overflow用户
提问于 2012-03-08 02:20:17
回答 5查看 40.9K关注 0票数 158

我有以下代码:

代码语言:javascript
复制
return this.ObjectContext.BranchCostDetails.Where(
    b => b.TarrifId == tariffId && b.Diameter == diameter
        || (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
        || (!b.TarrifId.HasValue) && b.Diameter==diameter);

当我尝试运行代码时,我得到了这个错误:

LINQ to Entities无法识别方法'Boolean IsNullOrWhiteSpace(System.String)‘方法,并且此方法无法转换为存储表达式。“

我怎样才能解决这个问题并写出比这个更好的代码呢?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-03-08 02:24:05

你需要更换

代码语言:javascript
复制
!string.IsNullOrWhiteSpace(b.Diameter)

使用

代码语言:javascript
复制
!(b.Diameter == null || b.Diameter.Trim() == string.Empty)

对于Linq to Entities,它被转换为:

代码语言:javascript
复制
DECLARE @p0 VarChar(1000) = ''
...
WHERE NOT (([t0].[Diameter] IS NULL) OR (LTRIM(RTRIM([t0].[Diameter])) = @p0))

与Linq to SQL几乎相同,但不完全相同

代码语言:javascript
复制
DECLARE @p0 NVarChar(1000) = ''
...
WHERE NOT (LTRIM(RTRIM([t0].[TypeName])) = @p0)
票数 273
EN

Stack Overflow用户

发布于 2013-01-24 20:41:59

在这种情况下,区分IQueryable<T>IEnumerable<T>非常重要。简而言之,IQueryable<T>由LINQ提供程序处理,以提供优化的查询。在此转换过程中,并不是所有的C#语句都受支持,因为不可能将它们转换为特定于后端的查询(例如SQL),或者因为实现者没有预见到对语句的需求。

相反,IEnumerable<T>是针对具体对象执行的,因此不会被转换。因此,可以与IEnumerable<T>一起使用的构造不能与IQueryable<T>一起使用,而且由不同LINQ提供程序支持的IQueryables<T>也不支持相同的函数集,这是很常见的。

但是,有一些变通方法(如Phil's answer)可以修改查询。此外,作为一种更通用的方法,可以在继续指定查询之前返回到IEnumerable<T>。然而,这可能会影响性能-特别是在限制(例如where子句)上使用它时。相比之下,在处理转换时,性能影响要小得多,有时甚至不存在-这取决于您的查询。

因此,上面的代码也可以像这样重写:

代码语言:javascript
复制
return this.ObjectContext.BranchCostDetails
    .AsEnumerable()
    .Where(
        b => b.TarrifId == tariffId && b.Diameter == diameter
        || (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
        ||(!b.TarrifId.HasValue) && b.Diameter==diameter
    );

注意: Ths代码将比Phil's answer具有更高的性能影响。然而,它显示了原理。

票数 21
EN

Stack Overflow用户

发布于 2016-12-02 11:59:34

使用表达式访问器来检测对string.IsNullOrWhiteSpace的引用,并将它们分解为更简单的表达式(x == null || x.Trim() == string.Empty)

下面是一个扩展的访问者和一个使用它的扩展方法。它不需要特殊的配置就可以使用,只需调用WhereEx而不是Where。

代码语言:javascript
复制
public class QueryVisitor: ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Method.IsStatic && node.Method.Name == "IsNullOrWhiteSpace" && node.Method.DeclaringType.IsAssignableFrom(typeof(string)))
        {
            //!(b.Diameter == null || b.Diameter.Trim() == string.Empty)
            var arg = node.Arguments[0];
            var argTrim = Expression.Call(arg, typeof (string).GetMethod("Trim", Type.EmptyTypes));

            var exp = Expression.MakeBinary(ExpressionType.Or,
                    Expression.MakeBinary(ExpressionType.Equal, arg, Expression.Constant(null, arg.Type)),
                    Expression.MakeBinary(ExpressionType.Equal, argTrim, Expression.Constant(string.Empty, arg.Type))
                );

            return exp;
        }

        return base.VisitMethodCall(node);
    }
}

public static class EfQueryableExtensions
{
    public static IQueryable<T> WhereEx<T>(this IQueryable<T> queryable, Expression<Func<T, bool>> where)
    {
        var visitor = new QueryVisitor();
        return queryable.Where(visitor.VisitAndConvert(where, "WhereEx"));
    }
}

因此,如果您运行myqueryable.WhereEx(c=> !c.Name.IsNullOrWhiteSpace()),它将在传递给任何对象(linq to sql/entities)之前转换为!(c.Name == null || x.Trim() == ""),并转换为sql。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9606979

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档