Странность лямбда-выражений в условии LINQ to SQL 'where' - PullRequest
3 голосов
/ 28 июля 2010

Я работаю над 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);

Я получаю ошибку:

Значение не может быть нулевым. Имя параметра: текст

Я думал, что лямбда-выражение будет выполнять то же самое, поскольку значение поиска равно нулю, но это явно не тот случай.

Как мне решить эту проблему?

Ответы [ 3 ]

3 голосов
/ 28 июля 2010

Поскольку это выражение, обычная логика условного оператора (без оценки ложного выражения) не применяется автоматически. Поскольку выражение фактически переводится в выражение запроса SQL, LINQ to SQL оценивает параметры условия, и в данном случае это null. В то время как LIKE null является допустимым синтаксисом SQL, очевидно, что LINQ to SQL не ценит, что его передают в ноль. Вам нужно будет создать два разных запроса, один для нулевого термина, другой для ненулевого термина.

Либо так, либо передайте что-то вроде string.Empty на Contains. Единственное влияние здесь будет невозможность использования индекса для столбца, так как сервер будет выполнять повторную условную оценку для каждой строки, заставляя сканирование таблицы. Я бы посоветовал использовать два запроса без условия.

1 голос
/ 28 июля 2010

Чтобы добавить к другим ответам, если у вас есть , чтобы следовать этому идеалу, вы можете просто сделать это вместо:

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

Прежде чем слепо реализовать это, если вы должны были это сделать, прочитайте ответ Адама, чтобы узнать о последствиях.

1 голос
/ 28 июля 2010

Содержит ожидаемую строку.Вы должны передать string.Emtpy.

u.UserName.Contains(search)

Если вы попробуете это, он скомпилируется, но вы получите ошибку времени выполнения:

string str = "Leniel";

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

Ошибка:

Value cannot be null.
Parameter name: value
...