Как я могу сначала заполнить поле FK, используя EF-код?

#entity-framework-4.1 #ef-code-first #code-first

#entity-framework-4.1 #ef-code-first #сначала код

Вопрос:

У меня есть рассылка класса со статусом, который выглядит следующим образом:

 public class Mailout
{
   public int Id {get; set; }
   public string Name {get; set; }
   public MailoutStatus Status { get; set; }
}
public class MailoutStatus
{
   public int Id { get; set; }
   public string Name { get; set;}
}
  

Когда я вставляю рассылки и устанавливаю свойство Status, они вставляются правильно. Когда я извлекаю их, статус всегда равен null. Поскольку у меня нет (и не хочу) идентификатора статуса в моем классе рассылки, у меня нет способа восстановить его после факта. Как мне сказать EF, чтобы он заполнял это поле с готовностью, а не лениво?

Я надеюсь, что смогу что-то настроить в OnModelCreating (), поскольку я хочу такого поведения постоянно, а не как вариант, который я могу использовать иногда, манипулируя моими запросами LINQ-to-Entities.

Ответ №1:

Вам нужно сделать ваши свойства навигации виртуальными.

Комментарии:

1. @Slauma: Нет. Для корректной работы отложенной загрузки вместо возврата null. Вы можете использовать Include(x=>x.Property) для быстрой загрузки.

2. Это был скорее риторический вопрос 😉 Потому что он сказал в вопросе, что он не хочет использовать отложенную загрузку, но нетерпеливую загрузку. Тогда создание виртуальных реквизитов не помогло бы.

3. @Slauma: вы знаете, в чем проблема XY? У пользователя проблема X, и он думает, что единственным решением является Y, поэтому он спрашивает о Y. Но реальное решение находится внутри X. Если вы внимательно прочитали его вопрос, отложенная загрузка у него не работает, поэтому он предположил, что единственный способ решить проблему — это ускорить загрузку, что не так.

4. Я знаю, что вы имеете в виду, но я прочитал вопрос по-другому. Неважно, теперь есть два ответа, которые охватывают разные интерпретации вопроса.

5. @Diego — ты молодец, и ты совершенно прав насчет моей проблемы «запрашиваю X, на самом деле нужно Y». @Slauma, спасибо также за ваш ответ!

Ответ №2:

В ModelBuilder нет такой опции, чтобы настроить автоматическую загрузку свойств навигации в каждом запросе. Вы должны указывать его запрос за запросом. В качестве обходного пути вы могли бы инкапсулировать нетерпеливую загрузку в какой-либо метод или свойство, например, в контексте:

 public class MyContext : DbContext
{
    public DbSet<Mailout> Mailouts { get; set; }
    public IQueryable<Mailout> MailoutsWithStatus
    {
        get { return Mailouts.Include(m => m.Status); }
    }
    // ...
}
  

А затем использовать в ваших запросах:

 context.MailoutsWithStatus.Where(...) ... etc.
  

Это только идея, она не проверялась.

Ответ №3:

Взяв из Employee Info Starter Kit — предстоящего выпуска MVC, вот фрагмент, который довольно хорошо работает для быстрой загрузки объектов при использовании:

 public class Employee
{
    ...
    public int? ReportsTo { get; set; }

    [ForeignKey("ReportsTo")]
    public virtual Employee Supervisor { get; set; }

    /// <summary>
    /// Children object collection of foreign key relation 
    /// </summary>
    public virtual List<Employee> Subordinates { get; set; }
}