Прочитайте этой документации , которая объясняет, как linq и c # могут испытывать разрыв соединения.
Поскольку ожидается, что выражения Linq будут сокращены до чего-то другого, кроме простых методов, вы можете обнаружить, что этот код ломается, если позже он используется в некотором контексте, отличном от Linq to Objects.
Это сказал
String.IsNullOrEmpty(fromname) ||
( !String.IsNullOrEmpty(fromname) &&
msg.FromName.ToLower().Contains(fromname.ToLower())
)
Плохо сформирован, так как действительно должно быть
String.IsNullOrEmpty(fromname) ||
msg.FromName.ToLower().Contains(fromname.ToLower())
, что делает его понятным и ясным, что вы полагаетесь на msg и msg.FromName, чтобы оба также были ненулевыми.
Чтобы сделать вашу жизнь проще в c #, вы можете добавить следующий метод расширения строки
public static class ExtensionMethods
{
public static bool Contains(
this string self, string value, StringComparison comparison)
{
return self.IndexOf(value, comparison) >= 0;
}
public static bool ContainsOrNull(
this string self, string value, StringComparison comparison)
{
if (value == null)
return false;
return self.IndexOf(value, comparison) >= 0;
}
}
Тогда используйте:
var messages = (from msg in dc.MessageItems
where msg.FromName.ContainsOrNull(
fromname, StringComparison.InvariantCultureIgnoreCase)
select msg);
Однако это не проблема. Проблема заключается в том, что аспекты системы Linq to SQL пытаются использовать значение fromname
для создания запроса , который отправляется на сервер.
Поскольку fromname
является переменной, механизм трансляции отключается и выполняет то, что от него требуется (генерируя строчное представление fromname
, даже если оно равно null, что вызывает исключение).
в этом случае вы можете сделать то, что вы уже обнаружили: оставить запрос как есть, но убедитесь, что вы всегда можете создать ненулевое значение fromname с желаемым поведением, даже если оно пустое.
Возможно, лучше было бы:
IEnumerable<MessageItem> results;
if (string.IsNullOrEmpty(fromname))
{
results = from msg in dc.MessageItems
select msg;
}
else
{
results = from msg in dc.MessageItems
where msg.FromName.ToLower().Contains(fromname)
select msg;
}
Это не так здорово, поскольку запрос содержал другие ограничения и, следовательно, требовал большего дублирования, но для простого запроса на самом деле должен получиться более читаемый / поддерживаемый код. Это неприятно, если вы полагаетесь на анонимные типы, но, надеюсь, это не проблема для вас.