Я несколько сбит с толку этим, но у меня есть дикое предположение.Если последовательность msg
представляет собой IQueryable<T>
, который преобразуется в запрос SQL, то поведение этих двух фрагментов может отличаться.Предположим, у вас есть:
var msg =
from m in dataContext.MyTable
select m;
Ваш первый фрагмент вызовет перечисление всей последовательности msg
, тем самым введя нефильтрованную команду SELECT…FROM
в базу данных и выбрав все строки в вашей таблице.
foreach (var m in msg)
С другой стороны, ваш второй фрагмент применяет фильтр к вашей последовательности до того, как будет перечислен.Таким образом, команда, выданная базе данных, представляет собой SELECT…FROM…WHERE
.
foreach (var m in msg.Where(z => (z.PhoneNumber == null || z.PhoneNumber == "")))
. Существуют различные случаи, когда поведение фильтра, применяемого в .NET, будет отличаться от его перевода в Transact-SQL.С одной стороны, чувствительность к регистру.В вашем случае я предполагаю, что несоответствие вызвано записями, чьи PhoneNumber
состоят из пробелов, поскольку они могут совпадать с пустой строкой в SQL Server.
Чтобы проверить эту возможность, проверьте, что произойдет, если вы измените свойвторой фрагмент:
foreach (var m in msg.ToList().Where(z => (z.PhoneNumber == null || z.PhoneNumber == "")))
Редактировать : Ваша проблема может заключаться в том, что ваш запрос выполняется снова при последующем доступе (когда вы проверяете, был ли установлен PhoneNumber
).
Если вы выполните:
foreach (var m in msg.Where(z => (z.PhoneNumber == null || z.PhoneNumber == "")))
{
m.PhoneNumber = …
}
bool stillHasNulls = msg.Any(z => z.PhoneNumber == null || z.PhoneNumber == "");
Вы обнаружите, что stillHasNulls
может по-прежнему оцениваться в true
, так как ваше назначение m.PhoneNumber
теряется при повторной оценкеmsg
sequence (в приведенном выше случае, когда вы выполняете msg.Any
, который выдает команду EXISTS
для базы данных).
Для сохранения ваших m.PhoneNumber
назначений вам нужно либо сохранитьих в базу данных (если это то, что вы хотите), или убедитесь, что вы каждый раз обращаетесь к одним и тем же элементам последовательности.Один из способов сделать это состоит в том, чтобы предварительно заполнить последовательность как коллекцию, используя ToList
.
msg = msg.Where(z => (z.PhoneNumber == null || z.PhoneNumber == "")).ToList();
foreach (var m in msg)
{
m.PhoneNumber = …
}
. В приведенном выше коде фильтр по-прежнему передается в базу данных как SELECT…FROM…WHERE
,но результат оценивается с нетерпением, а затем сохраняется в виде списка в msg
.Любые последующие запросы на msg
будут оцениваться по предварительно заполненной коллекции в памяти (которая будет содержать любые новые значения, которые вы присваиваете ее элементам).