Попытка выяснить разницу между ленивой и нетерпеливой загрузкой в структуре сущностей. Скажем, у меня есть следующие модели:

public interface IBaseEntityObject 
{
    public int Id {get; set;}
}


public abstract class BaseEntityObject : IBaseEntityObject
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id {get; set;}
}


public class Folder : BaseEntityObject
{   
    [DataMember]
    public string Name {get; set;}

    [DataMember]
    public virtual List<Letter> Letters {get; set;} 
}


public abstract class Letter : BaseEntityObject
{   
    [DataMember]
    public string Title {get; set;}

    [DataMember]
    public string Content {get; set;}

    public virtual Folder Folder {get; set;}

    [DataMember]
    public int FolderId {get; set;}

    [DataMember]
    public DateTime CreationDate {get; set;}
}

public class OutgoingLetter : Letter
{
    // .. OutgoingLetter properties
}

public class ReceviedLetter : Letter
{
    // .. ReceviedLetter properties
}


public class MyDbContext : DbContext
{
    public DbSet<Folder> Folders {get; set;}

    public DbSet<Letter> Letters {get; set;}


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Folder <-> Letters       
        modelBuilder.Entity<Letter>()
        .HasRequired(t => t.Folder)
        .WithMany(f => f.Letters)
        .HasForeignKey(t => t.FolderId)
        .WillCascadeOnDelete(true);
    }
}

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

Я читал, что отключение отложенной загрузки выполняется путем ее настройки в ctor с помощью установки для свойства EnableLazyLoading значения false и удаления виртуального ключевого слова из списка букв.

В чем будет разница, если я просто использую Include (x => x.Lettters) всякий раз, когда прошу папку, и оставляю включенной отложенную загрузку? Включить нельзя, если включена отложенная загрузка?

Более того, есть ли связь между свойством Folder, которое хранится в модели Letter, с отложенной загрузкой? Я не использую папку, когда запрашиваю письмо, но большинство моделей, которые я видел, содержат свойство «Отец» в отношении «один ко многим», и я действительно не понимаю, почему.

Благодарность!

2
user5326354 19 Фев 2016 в 15:42

3 ответа

Лучший ответ

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

Ага, правильно.

Я читал, что отключение отложенной загрузки выполняется путем ее настройки в ctor с помощью установки для свойства EnableLazyLoading значения false и удаления виртуального ключевого слова из списка букв.

Если вам никогда не нужна отложенная загрузка определенного свойства, удалите ключевое слово virtual. Если вам это иногда нужно, а иногда нет, отключите отложенную загрузку при создании нового контекста в своем коде.

В чем будет разница, если я просто использую Include (x => x.Lettters) всякий раз, когда прошу папку, и оставляю включенной отложенную загрузку? Включить нельзя, если включена отложенная загрузка?

Они не влияют друг на друга. Если вы не включите буквы и попытаетесь получить доступ к свойству, EF сделает еще один вызов db для их получения (ленивая загрузка), если вы включите их, они будут доступны и никаких дополнительных вызовов к базе данных не будет.

Более того, есть ли связь между свойством Folder, которое хранится в модели Letter, с отложенной загрузкой? Я не использую папку, когда запрашиваю письмо, но большинство моделей, которые я видел, содержат свойство «Отец» в отношении «один ко многим», и я действительно не понимаю, почему.

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

2
Alexander Derck 19 Фев 2016 в 12:48

Вы можете использовать Include также с включенной отложенной загрузкой. Отсутствие использования Include делает код более понятным, поэтому обычно я использую Include только там, где у меня есть проблемы с производительностью.
Кроме того, навигация может меняться в течение жизненного цикла проекта, поэтому при ленивой загрузке вам не нужно об этом помнить.
Кроме того, вы не можете использовать ленивую загрузку во время сериализации, иначе вы, вероятно, сериализуете всю базу данных.

Просто для информации, Include также часто генерирует очень уродливые запросы (но у меня никогда не было проблем с производительностью).

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

0
bubi 19 Фев 2016 в 12:51

Я читал, что отключение Lazy load выполняется путем его настройки в ctor с помощью установки для свойства EnableLazyLoading значения false и удаления виртуального ключевого слова из списка букв

Бо не умны. Это все равно, что вынуть аккумулятор из машины, чтобы просто заглушить двигатель.

Lazy loading ENABLED не означает, что она ИСПОЛЬЗУЕТСЯ, то же самое с виртуальным

В чем будет разница, если я просто использую Include (x => x.Lettters) всякий раз, когда прошу папку, и оставляю включенной отложенную загрузку?

Этим последним можно будет использовать ленивую загрузку (чего нельзя будет после саботажа).

Включить нельзя, если включена отложенная загрузка?

Кто говорит? Может полностью - в этом случае ленивая загрузка просто не будет происходить для уже включенных элементов, что дает вам свободу выбирать ленивую загрузку или нет в каждом конкретном случае.

0
TomTom 19 Фев 2016 в 12:50