LINQ to SQL с нулевыми значениями - PullRequest
3 голосов
/ 04 февраля 2012

Может кто-нибудь помочь мне разобраться?

Приведенный ниже код работает нормально и попадает в статут if

foreach (var m in msg)
{
    if (string.IsNullOrEmpty(m.PhoneNumber))
    {
        m.PhoneNumber = (from c in db.Customers
                            where c.CustomerID == m.CustomerID
                            select c.PhoneNumber).Single();
    }
}

Однако в приведенном ниже коде phoneNumber никогда не устанавливается

foreach (var m in msg.Where(z => (z.PhoneNumber == null || z.PhoneNumber == "")))
{
     m.PhoneNumber = (from c in db.Customers
                      where c.CustomerID == m.CustomerID
                      select c.PhoneNumber).Single();
}

Я предполагаю, потому что верхний код на самом деле оценивает выражение, тогда как приведенный ниже не соответствует. Если это так, то как можно проверить наличие нулевого значения в неоцененном запросе LINQ?

РЕДАКТИРОВАТЬ Чтобы избежать путаницы, вот как заполняется сообщение в обоих случаях

    var msg = from m in db.Messages
              where (m.StatusID == (int)MessageStatus.Submitted && m.MessageBoxTypeID == (int)MessageBoxType.Outbox)
              select m;

1 Ответ

1 голос
/ 04 февраля 2012

Я несколько сбит с толку этим, но у меня есть дикое предположение.Если последовательность 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 будут оцениваться по предварительно заполненной коллекции в памяти (которая будет содержать любые новые значения, которые вы присваиваете ее элементам).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...