开发者

Lambda expression weirdness in a LINQ to SQL 'where' condition

I am working on an ASP.NET MVC application which uses the repository pattern with LINQ to SQL as my data source. In my repository I expose the following method:

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

I am able to call this by saying:

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

开发者_如何学编程But if I try doing (when search is null)

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

I get the error:

Value cannot be null. Parameter name: text

I thought the lambda expression would execute the same thing since the value of search is null, but this is clearly not the case.

How do I fix this problem?


Because this is an expression, normal conditional operator logic (not evaluating the false expression) don't automatically apply. Since the expression is actually being translated into a SQL query expression, LINQ to SQL is evaluating the parameters of the condition, and in this case it's null. While LIKE null is valid SQL syntax, evidently LINQ to SQL doesn't appreciate being passed null. You'll have to construct two different queries, one for a null term, one for a non-null term.

Either that, or pass something like string.Empty to Contains. The only impact here will be the inability to use an index on the column, since the server will be doing a repeated conditional evaluation on every row, forcing a table scan. I'd advise using two queries without the conditional.


To add to the other answers, if you have to follow this ideal, you could simply do this instead:

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

Before blindly implementing this, if you were to do so, please read Adam's answer to learn of consequences.


Contains expects a string. You should pass string.Emtpy.

u.UserName.Contains(search)

If you try this, it'll compile but you'll get a runtime error:

string str = "Leniel";

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

Error:

Value cannot be null.
Parameter name: value
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜