EF4 POCO Свойство навигации "один ко многим" имеет значение null

Я использую VS2010, функцию EF4 CTP (последний выпуск) и объекты POCO, такие как пример ниже:

class Person
{
 public int ID { get; set; }
 public string Name { get; set; }
 public virtual IList<Account> Accounts { get; set; }
 ...
}

class Account
{
 public string Number { get; set; }
 public int ID { get; set; }
 ...
}

Для краткости предположим, что context ниже — это объект контекста для EF4. У меня есть сопоставление dbml между типами сущностей и базой данных, и я использую его без проблем:

Person doug = context.Persons.CreateObject();
doug.Name = "Doug";    
context.Add(doug);
context.Save();
doug.Accounts.Add(new Account() { Name = "foo" });
context.Save(); // two calls needed, yuck

На данный момент в базе данных есть запись о человеке с именем «Doug» и запись об учетной записи «foo». Я могу запросить и вернуть эти записи. Но если вместо этого я попытаюсь добавить учетную запись до сохранения Person, список учетных записей будет пустым (прокси-сервер еще не создал экземпляр для этого свойства). См. следующий пример:

Person doug = context.Persons.CreateObject();
doug.Name = "Doug";
doug.Accounts.Add(new Account() { Name = "foo" }); // throws null reference exception
context.Add(doug);
context.Save();

Кто-нибудь еще сталкивался с этим? Еще лучше, кто-нибудь нашел хорошее решение?


person Douglas R    schedule 05.01.2010    source источник


Ответы (3)


Person doug = context.Persons.CreateObject();

doug.Name = "Doug";

context.Add(doug);
doug.Accounts.Add(new Account() { Name = "foo" });
context.Save();

Это будет работать

person Praneeth    schedule 21.11.2010

Да и да!

Когда вы создаете новый POCO (в отличие от CreateObject из контекста), вам не предоставляются прокси. Это может показаться очевидным, но мне пришлось явно напомнить себе об этом поведении, когда я пытался решить подобную проблему. (Я знаю, что это не та ситуация, которую вы описали в вопросе, но следует признать общую проблему).

Инициализация коллекций в конструкторе POCO не мешает правильному поведению отложенной загрузки прокси-сервера EF4, как я наблюдал в своем собственном тестировании.

Хорошо, все это сказано, теперь я вижу ваш комментарий к предыдущему ответу - почему у меня нет коллекции проксированных адресов, когда я запрашиваю нового человека из моего контекста? У вас включена ленивая загрузка в контексте? Видя, как мы работаем со свойствами навигации, я понял, как отключение ленивой загрузки может изменить ситуацию в этой ситуации.

person kdawg    schedule 06.01.2010

ISTM, что если вы ожидаете, что фреймворк сделает все это за вас, то у вас действительно не будет «POCO», не так ли? Возьмите свой класс Person с кодом выше. Каким вы ожидаете состояние свойства Accounts после построения без конструктора, если EF не был задействован? Мне кажется, что CLR гарантирует, что они будут нулевыми.

Да, прокси-серверы могут инициализировать это, когда это необходимо для материализации значений БД, но в EF «POCO» на самом деле означает «Обычный». Не «что-то, упакованное кодом, сгенерированным во время выполнения, которое мы притворяемся« простым »».

person Craig Stuntz    schedule 05.01.2010
comment
Я отредактировал свой вопрос, чтобы уточнить, что я спрашиваю не о сценарии конструктора, а о поведении context.Persons.CreateObject();. Меня смущает то, что если фреймворк будет «владеть» этими навигационными свойствами после того, как я сохраню объект, почему он не сделает этого при создании экземпляра Entity? У меня нет проблем с инициализацией коллекций в конструкторах моих сущностей, но если фреймворк ожидает, что эти коллекции будут null, кажется, я помещаю объект в плохое состояние. - person Douglas R; 05.01.2010