LINQ to Entities - Множественные объединения - Исключение нулевой ссылки при выборе 'Select'

Я пытаюсь преобразовать запрос SQL в запрос LINQ to entity, но у меня возникли проблемы с блоком LINQ select.

Вот SQL-запрос, который работает так, как ожидалось:

SELECT distinct( p.PendingID,
        p.Description,
        p.Date,
        f.Status,
        u.UserName,
        m.MapID
    FROM    Pending p
    JOIN    Users u 
   ON p.UserID = u.UserID
    LEFT JOIN Forks f 
   ON p.PendingID = f.PendingID
    LEFT JOIN Maps m
      ON f.ForkID = m.ForkID
    ORDER BY p.Date DESC

Вот запрос LINQ to entity в том виде, в котором он есть у меня:

var pList = (from pending in pendingItems
// JOIN
from user in userList.Where(u => pending.UserID == u.UserID)
// LEFT OUTER JOIN
from fork in forkList.Where(f => pending.ID == f.PendingID)
.DefaultIfEmpty()
// LEFT OUTER JOIN
from map in mapList.Where(m => fork.ID == m.ForkID)
.DefaultIfEmpty()
orderby pending.Date descending
select new
{
 ItemID = pending.ID,                 // Guid
 Description = pending.Description,   // String
 Date = pending.Date,                 // DateTime
 Status = fork.Status,               // Int32 (*ERROR HERE*)
 UserName = user.UserName,            // String 
 MapID = map.ID                       // Guid (*ERROR HERE*)
})
.Distinct()
.ToList();

Запрос LINQ завершается ошибкой в ​​одной из следующих 2 строк, которые пытаются присвоить значения, полученные из результатов левого внешнего соединения. Если следующие строки опущены, запрос LINQ завершится без ошибок:

Status = fork.Status,
MapID = map.ID

Почему эти 2 назначения свойств не работают в блоке выбора запроса LINQ?


person geekAlias    schedule 21.12.2010    source источник
comment
Вы действительно запускаете это против EF или факсимиле вашей базы данных в памяти? Во-вторых, находится ли этот код в LINQPad и можете ли вы проверить сгенерированный SQL (если он соответствует EF)?   -  person Anthony Pegram    schedule 21.12.2010
comment
Я думаю, что это ошибка компилятора, поэтому он видит ошибки в обеих строках.   -  person tster    schedule 21.12.2010
comment
tster: в заголовке сообщения указано Null Reference Exception, поэтому я сомневаюсь, что это ошибка компилятора.   -  person Gabe    schedule 21.12.2010
comment
@Anthony: я работаю с коллекциями в памяти после того, как они были ранее извлечены из контекста EF.   -  person geekAlias    schedule 21.12.2010
comment
@tster: ошибок компилятора нет; только проблемы во время выполнения.   -  person geekAlias    schedule 21.12.2010


Ответы (1)


Проблема в том, что из-за ваших внешних соединений fork и map могут быть нулевыми. Конечно, когда они равны нулю, вы не можете получить доступ к их свойствам. Вам может понадобиться что-то вроде этого:

Status = (fork == null) ? null : fork.Status,
MapID = (map == null) ? null : map.ID 
person Gabe    schedule 21.12.2010
comment
Они не могут быть нулевыми, потому что DefaultIfEmpty возвращает коллекцию, а если их нет, возвращает одноэлементную коллекцию. Однако значение в коллекции может быть нулевым. - person tster; 21.12.2010
comment
tster: переменные map и fork перебирают значения, возвращаемые DefaultIfEmpty, поэтому они действительно могут быть нулевыми. - person Gabe; 21.12.2010
comment
Блин, я привык смотреть на let x = ..., а не на несколько предложений from. - person tster; 21.12.2010
comment
Спасибо за решение! Работал как шарм. Я забыл о возможности того, что весь объект может иметь значение NULL в каждом случае, когда применялись внешние соединения. - person geekAlias; 21.12.2010