Обнуляемая проекция объекта в Entity Framework - PullRequest
3 голосов
/ 26 сентября 2008

У меня есть следующая схема базы данных SQL Server 2005:

CREATE TABLE Messages (
   MessageID int,
   Subject varchar(500),
   Text varchar(max) NULL,
   UserID NULL
)

Столбец «UserID», который может быть нулевым, является внешним ключом и связывается с таблицей

CREATE TABLE Users (
   UserID int,
   ...
)

Теперь у меня есть несколько классов POCO с именами Message, User и т. Д., Которые я использую в следующем запросе:

public IList<Message> GetMessages(...) {
  var q = (from m in dataContext.Messages.Include("User")
           where ...
           select m); // could call ToList(), but...

  return (from m in q
          select new Message {
            ID = m.MessageID,
            User = new User {
              ID = m.User.UserID,
              FirstName = m.User.FirstName,
              ...
            }
          }).ToList();
}

Теперь обратите внимание, что я советую структуре сущностей - используя Include ("Users") - загрузить пользователя, связанного с сообщением, если оно есть. Также обратите внимание, что я не вызываю ToList () после первого оператора LINQ. При этом из базы данных будут возвращены только указанные столбцы в списке проекций - в этом случае MessageID, UserID, FirstName.

В этом и заключается проблема - как только Entity Framework встречает сообщение с UserID == NULL, оно выдает исключение, говоря, что не может преобразоваться в Int32, поскольку значение БД равно NULL.

Если я изменю последние пару строк на

return (from m in q
        select new Message {
           ID = m.MessageID,
           User = m.User == null ? null : new User {
              ID = m.User.UserID,
              ...
           }
        }).ToList()

затем генерируется исключение NotSupportedException во время выполнения, сообщающее, что оно не может создать постоянный тип User, и поддерживаются только такие примитивы, как int, string, guid.

У кого-нибудь есть идеи, как с этим справиться, кроме материализации результатов сразу после первого утверждения и последующего использования проекции в памяти? Спасибо.

Ответы [ 3 ]

2 голосов
/ 30 сентября 2008

Вы забыли включить объявление своего класса "Message", но я подозреваю, что свойство UserID в этом классе не объявлено как обнуляемый тип. Если это так, измените его с "int" на "int?" (обнуляемый int).

0 голосов
/ 26 сентября 2008

Поскольку вы выполнили .Include("Users"), вы можете просто просмотреть свойство User в объекте Message, чтобы получить необходимую информацию.

0 голосов
/ 26 сентября 2008

Я подозреваю, что ваши отношения не от 1 до 1.

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