【问题标题】:Lambda expression weirdness in a LINQ to SQL 'where' conditionLINQ to SQL 'where' 条件中的 Lambda 表达式怪异
【发布时间】:2010-07-28 13:06:30
【问题描述】:

我正在开发一个ASP.NET MVC 应用程序,它使用以LINQ to SQL 作为我的数据源的存储库模式。在我的存储库中,我公开了以下方法:

public IEnumerable<T> Find(Expression<Func<T, bool>> where)
{
    return _context.GetTable<T>().Where(where);
}

我可以这样称呼它:

repository<User>().Find(u => true);

但如果我尝试这样做(当搜索为空时)

repository<User>().Find(u => !string.IsNullOrEmpty(search) ? u.UserName.Contains(search) : true);

我得到错误:

值不能为空。参数名称:文本

我认为 lambda 表达式会执行相同的操作,因为 search 的值为 null,但显然不是这样。

我该如何解决这个问题?

【问题讨论】:

  • 你能显示更多上下文吗?惰性求值使 LINQ 在不了解您如何使用其输出的情况下难以分析。
  • IsNullOrEmpty 和 Contains 的参数都称为 value,因此错误不是来自它们。
  • @SWeko:string.Contains 不会抛出异常,表达式解析器对调用 string.Contains 以构造 LIKE 表达式的评估会。

标签: c# .net linq lambda expression-trees


【解决方案1】:

因为这是一个表达式,正常的条件运算符逻辑(不计算假表达式)不会自动应用。由于表达式实际上被转换为 SQL 查询表达式,因此 LINQ to SQL 正在评估条件的参数,在本例中为 null。虽然LIKE null 是有效的 SQL 语法,但显然 LINQ to SQL 不喜欢传递 null。您必须构建两个不同的查询,一个用于空词,一个用于非空词。

要么这样,要么将string.Empty 之类的东西传递给Contains。这里唯一的影响是无法在列上使用索引,因为服务器将对每一行进行重复的条件评估,从而强制进行表扫描。我建议使用两个不带条件的查询。

【讨论】:

    【解决方案2】:

    要添加到其他答案,如果您必须遵循这个理想,您可以简单地这样做:

    repository<User>.Find(u => string.IsNullOrEmpty(search) || 
                               u.UserName.Contains(search));
    

    在盲目实施此操作之前,如果您要这样做,请阅读亚当的回答以了解后果。

    【讨论】:

    • 我刚刚发现:repository.Find(u => (string.IsNullOrEmpty(search) || u.UserName.Contains(search)) && (!enabled. HasValue || u.Enabled == enabled.Value));我遇到和以前一样的问题。呸
    【解决方案3】:

    包含需要一个字符串。你应该通过string.Emtpy

    u.UserName.Contains(search)
    

    如果你尝试这个,它会编译但你会得到一个运行时错误:

    string str = "Leniel";
    
    if (str.Contains(null))
    {
        var num = 1;
    }
    

    错误:

    Value cannot be null.
    Parameter name: value
    

    【讨论】:

    • string.Contains 未被调用。表达式中对string.Contains 的调用被转换为SQL 中的LIKE 表达式。这个翻译是引发异常的原因。注意参数名称的不同(value vs. text
    猜你喜欢
    • 2017-07-22
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多