2015-02-04 4 views
1

Где я ошибаюсь? Я получаю NullReferenceExeption в навигационной собственности Events. Он отмечен как virtual и LazyLoadingEnabled явно разрешен.EF: Загрузка связанных объектов Lazy way dont work

программный код:

using (var db = new Db()) 
{ 
    var person = new Person(); 
    person.Name = "bla bla"; 
    db.Persons.Add(person); 
    person.Events = new List<Event>(1); 
    person.Events.Add(new Event() { Description = "ABC", At = DateTime.Now }); 
    db.SaveChanges(); 
} 

using (var db = new Db()) 
{ 
    var person = db.Persons.First(); 

    Console.WriteLine(person.Events == null); //Output: True 
    Console.WriteLine(person.Events.Count); //System.NullReferenceException 
} 

Явная погрузочные работы:

var person = db.Persons.First(); 
db.Entry(person).Collection(p => p.Events).Load(); 
Console.WriteLine(person.Events == null); //Output: False 
Console.WriteLine(person.Events.Count); //1 

Классы Структура:

class Db : DbContext 
{ 
    public Db() 
    { 
     Database.SetInitializer(new DropCreateDatabaseAlways<Db>()); 
     Configuration.LazyLoadingEnabled = true; 
    } 

    public DbSet<Person> Persons { get; set; } 
    public DbSet<Event> Events { get; set; } 
} 

class Person 
{ 
    public int id { get; set; } 
    public string Name { get; set; } 

    public virtual List<Event> Events { get; set; } 
} 

class Event 
{ 
    public int id { get; set; } 
    public DateTime At { get; set; } 
    public string Description { get; set; } 

    public Person Person { get; set; } 
    public int PersonId { get; set; } 
} 
+0

Я думаю, что ваше отношение внешних ключей неверно –

+0

Возможно, это что-то связано с версией EF - вы обновили ее в последнее время? Не могли бы вы опубликовать версию, которую используете? – Default

+0

@Default, когда я создаю объекты, я добавлю свойство для Person in Event, указав, что событие имеет отношения с Лицом, а также измените Список на Icollection

ответ

2

Ваши классы моделей должны быть общедоступными для ленивой загрузки. Измените class Person и class Event на public class Person и т. Д., И ваша тестовая программа начнет работать.

-1

Это просто.

Создать конструктор по умолчанию в классе Person и инициализации коллекции событий, как

public Person() 
{ 
    Events = new HashSet<Event>(); 
} 

И добавить виртуальную собственность с типом лица в классе Event

EDIT: В EF codefirst вы ответственны за инициализацию сбора и EF отвечает для заполнения этой коллекции из базы данных

+0

Я пробовал это, прежде чем я спросил. Результат: Событие не является нулевым, но EMPTY. – dovid

+0

Возможно, этот комментарий будет полезен [комментарий] (http://stackoverflow.com/questions/28322501/ef-loading-related-entities/28322796?noredirect=1#comment44992926_28322501), или у вас просто нет данных в базе данных – vasilyk

+0

также , если я загружаю explcity 'db.Entry (person) .Collection (p => p.Events) .Load();', его работа без инициализатора конструктора. – dovid

-1

Заменить new Person() на context.Persons.Create().

Это даст вам прокси-сервер Personity Framework, а не Person. Этот прокси-класс происходит от Person, но имеет свойство Events, переопределенное логикой загрузки Lazy.

Однако это не устраняет основную проблему вашего кода. Это повторение контекста. Которые вы не должны делать.

+0

мой вопрос касается второй секции 'using'. что класс 'Person', созданный EF – dovid

-1

В коде нет ничего плохого: если вы делаете Count в нулевой коллекции, вы всегда будете получать NullReferenceException - это не связано с Entity Framework, это .NET.

Существует различие между пустой коллекцией и пустой коллекцией.

Теперь, если вы хотите, чтобы избежать таких NullReferenceException исключения, вы всегда можете начать список в конструктор по умолчанию, как в:

class Person 
{ 
    public Person() 
    { 
     Events = new List<Event>(); 
    } 

    public int id { get; set; } 
    public string Name { get; set; } 

    public virtual List<Event> Events { get; set; } 
} 
+0

в ленивой загрузке, может быть пустым. прокси-сервер Entity Framework инициализирует коллекцию. – dovid

+0

Я знаю, что это может быть null. Даже если при ленивой загрузке оно может быть нулевым, если только вы не инициализируете его в конструкторе по умолчанию, который я и другие указали. Боюсь, что вопрос непонятен: вы спрашивали, почему у вас есть «NullReferenceExeption». Причина в том, что коллекция имеет значение null. Похоже, вы должны спросить, почему коллекция null. –

+0

Я понял, извините, если не был ясен по вопросу. Упомянутая ошибка «NullReferenceExeption» была сделана так, чтобы наиболее четко показать, что ленивая загрузка не работает. – dovid

-1
public class Person 
{ 
    public Person() 
    { 
      Events = new List<Event>(); 
    } 

    public int id { get; set; } 
    public string Name { get; set; } 

    public virtual List<Event> Events { get; set; } 
} 

public class Event 
{  
    public int id { get; set; } 
    public DateTime At { get; set; } 
    public string Description { get; set; } 

    public Person Person { get; set; } 
    public int PersonId { get; set; } 
} 

Вы должны инициализировать любые Colection навигации properity с использованием тех же тип коллекции и НЕ 'HashSet', вот так.

+0

в ленивой загрузке, коллекция может быть нулевой. прокси-сервер Entity Framework инициализирует коллекцию. – dovid

Смежные вопросы