在LINQ to SQL'where'条件下Lambda表达式怪异

时间:2010-07-28 13:06:31

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

我正在使用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);

我收到错误:

  

值不能为空。参数名称:text

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

如何解决此问题?

3 个答案:

答案 0 :(得分:3)

因为这是一个表达式,所以不会自动应用正常的条件运算符逻辑(不评估false表达式)。由于表达式实际上被转换为SQL查询表达式,LINQ to SQL正在评估条件的参数,在这种情况下它是null。虽然LIKE null是有效的SQL语法,但显然LINQ to SQL不支持传递null。您将不得不构造两个不同的查询,一个用于空术语,一个用于非空术语。

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

答案 1 :(得分:1)

包含期望字符串。您应该通过string.Emtpy

u.UserName.Contains(search)

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

string str = "Leniel";

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

错误:

Value cannot be null.
Parameter name: value

答案 2 :(得分:1)

要添加其他答案,如果 遵循此理想,您可以改为:

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

在盲目实施之前,如果您这样做,请阅读Adam的回答以了解后果。