2013-05-03 2 views
5

Я использую EF Model сначала с объектами POCO и с пользовательскими DbContexts. Моя проблема в том, что настройка LazyLoadingEnabled=false ничего не влияет, свойства навигации по-прежнему загружаются. Ниже мой пример упрощен.Настройка LazyLoadingEnabled не работает в EF 5

Сущность программы. Программа может быть частью других программ:

namespace Domain.Entities 
{ 
    using System; 
    using System.Collections.Generic; 

    public partial class Program 
    { 
     public Program() 
     { 
      this.Programs = new HashSet<Program>(); 
     } 

     public int Id { get; set; } 
     public string Title { get; set; } 
     public string Description { get; set; } 
     public System.DateTime StartDate { get; set; } 
     public System.DateTime EndDate { get; set; } 
     public Nullable<int> ProgramId { get; set; } 

     public virtual ICollection<Program> Programs { get; set; } 
     public virtual Program OwnerProgram { get; set; } 
    } 
} 

DbContext:

namespace Infrastructure.Model 
{ 
    public class ProgramContext : DbContext 
    { 
     public ProgramContext() 
      : base("name=MyContainer") 
     { 
      Configuration.LazyLoadingEnabled = false; 
     } 

     public DbSet<Program> Programs { get; set; } 
    } 
} 

Вот как я использую его:

private ProgramContext _dbContext = new ProgramContext(); 

// GET api/program 
public IEnumerable<Program> GetPrograms() 
{ 
    List<Program> list = _dbContext.Programs.ToList(); 
    return list; 
} 

С выше образца, EF еще загружает программы и свойства OwnerProgram для класса программы. Я попытался удалить виртуальные ключевые слова, отключив создание прокси, а также проверил, что LazyLoadingEnabled=false на самой модели.

Я что-то упустил?

ответ

6

Эффект, который вы видите, называется связь fixup.

Фактически навигационные свойства не загружены явно. Запрос _dbContext.Programs.ToList() загружает только всю таблицу Programs из базы данных.Это простой SQL-запрос (например, SELECT * FROM ProgramsTable) без предложения WHERE и без каких-либо JOIN относящихся к ним строк.

Также здесь нет никакой ленивой загрузки (это действительно невозможно, если вы отключите ее и отключите даже динамические прокси) при доступе к свойствам навигации program.Programs и program.OwnerProgram.

Свойства навигации заполняются, когда результат вашего запроса материализуется, потому что ваш запрос (который загружает все программы) загрузит все программы, на которые могут ссылаться свойства навигации. EF обнаруживает, что эти связанные объекты уже находятся в памяти и автоматически помещают их в свойства навигации.

Вы можете проверить это, если вы не загружать все программы, но только, к примеру, один один:

Program program = _dbContext.Programs.FirstOrDefault(); 

Теперь program.Programs и program.OwnerProgram будет null - если загружаемый program не является частью из своей собственной коллекции program.OwnerProgram или ее собственный OwnerProgram.

+1

Спасибо, это то, что я вижу. Есть ли способ заставить EF не загружать свойства навигации, если я не использую .Include()? – gixen

+0

@gixen: Как сказано, на самом деле это не «загрузка». Исправление отношений просто помещает сущности в коллекции навигации и ссылки, которые уже загружены в любом случае. Таким образом, накладные расходы отсутствуют. Если вы хотите изменить объекты после загрузки, вам потребуется отслеживание изменений, и вы не можете отключить это поведение. Без отслеживания изменений в ситуациях, доступных только для чтения, вы можете попробовать '_dbContext.Programs.AsNoTracking(). ToList()'. Но я не уверен, поможет ли это в этом случае. – Slauma

+0

То, что я получаю от этого ответа, заключается в том, что нет способа загрузить весь объектный граф в EF без открытого контекста для ленивых свойств навигации загрузки. ИЛИ .Include («NavigationProtperyName») можно явно вызвать для загрузки свойств навигации, но это необходимо для каждого запроса. –

2

«EF-прежнему загружает свойства программ и OwnerProgram Программного класса»

Это правильное поведение, но вместо загрузки навигационных свойств лениво, он загружает их с нетерпением.

Это означает, что запросы базы данных, необходимые для получения значений свойства навигации, выполняются немедленно, когда объект Program извлекается и свойства навигации заполняются.

Когда LazyLoadingEnabled установлено в true, эти запросы не запускаются до тех пор, пока вы не попытаетесь получить доступ к свойствам навигации. Это также относится к тому, когда вы наводите указатель мыши на свойства навигации и подключаете отладчик, что может заставить вас думать, что сущности не загружаются лениво, когда они на самом деле - отладчик получает доступ к свойству навигации, поэтому Entity Framework загружает его.

Вы можете запустить профилировщик SQL, такой как this one, чтобы точно видеть, когда запросы запускаются при отладке кода.

0

С приведенным выше образцом EF по-прежнему загружает свойства Программного класса Program и OwnerProgram . Я попытался удалить виртуальные ключевые слова , отключив создание прокси, а также подтвердил, что LazyLoadingEnabled = false на самой модели.

Я что-то упустил?

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

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