我正在使用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,但显然不是这样。
如何解决此问题?
答案 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的回答以了解后果。