2

Trying to figure out the difference between Lazy and Eager loading in entity frameowrk. Say I have the following models:

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);
    }
}

Whenever I ask a folder from the data base, it's main purpose is for accessing the Letters in it.. Therefore, will it be best if I already load it from the beginning instead of making another database call when accessing the Letters property am I correct?

I've read that disabling the Lazy load is done by configuring it in the ctor with by setting the EnableLazyLoading property to false and removing virtual key word from the letters list.

What would be the difference if I just use Include(x => x.Lettters) whenever I ask for a folder and keep the Lazy loading enabled? Include can not be used when Lazy loading is enabled?

Moreover is there any relation between the Folder property that is held in Letter model to the lazy loading? I don't use the Folder when asking for a letter, yet most models around I've seen contain the Father property in one to many relationship and I don't really understand why.

Thanks!

3 Answers3

2

Whenever I ask a folder from the data base, it's main purpose is for accessing the Letters in it.. Therefore, will it be best if I already load it from the beginning instead of making another database call when accessing the Letters property am I correct?

Yup, correct.

I've read that disabling the Lazy load is done by configuring it in the ctor with by setting the EnableLazyLoading property to false and removing virtual key word from the letters list.

If you never want lazy loading for a certain property, remove the virtual keyword. If you sometimes need it and sometimes you don't, disable lazyloading when you create a new context in your code.

What would be the difference if I just use Include(x => x.Lettters) whenever I ask for a folder and keep the Lazy loading enabled? Include can not be used when Lazy loading is enabled?

They have no effect on eachother. If you don't include the letters, and you try to access the property, EF will make another call to db to fetch them (lazy loading), if you include them, they're available and no extra call to database is made.

Moreover is there any relation between the Folder property that is held in Letter model to the lazy loading? I don't use the Folder when asking for a letter, yet most models around I've seen contain the Father property in one to many relationship and I don't really understand why.

In most examples, the navigation property is defined in both ways, but if you never need to get the folder from a letter, it makes perfect sense not to define that property in your letter model.

Alexander Derck
  • 13,818
  • 5
  • 54
  • 76
  • And what is the difference between setting the lazy loading off and disabling the proxy creation? Should I disable both when I want to take care of the loading myself? –  Feb 19 '16 at 14:51
  • See [this answer](http://stackoverflow.com/a/7112470/3410196) about EF proxies. Basically a proxy is a virtual object EF creates which represents a record in your table. I wouldn't advise turning off proxy creation, because then EF won't take care of tracking changes for you anymore. Disabling lazy loading alone is enough to prevent lazy loading. – Alexander Derck Feb 19 '16 at 15:03
  • And when would I want to load properties lazily? It'll just make things slower, right? It's just a "protection" so if you forgot to load items yourself, EF will do it for you? –  Feb 19 '16 at 15:05
  • If you have a resultset but you don't need the navigation properties for all of them for example. If you need a related entity from 1 result out of a collection of 1000, it makes sense to access it through lazy loading (let EF do one extra call to database to get that entity) than fetching 1000 of which you will only use 1. – Alexander Derck Feb 19 '16 at 15:09
  • For example, using lazy loading I can load 1 letter from a folder instead of all them using include? Is that what you mean? How is that done? –  Feb 19 '16 at 15:15
  • That's not what I mean, imagine you get 1000 folders from the database, but you need the letters from only 1 of those folders, it's better to lazy load the letters for that one folder then, than getting the letters for all 1000 folders. But what you say is true, if you have a certain folder from the database for example, you can select a letter with name "letter1" and that will be lazy loaded: `var letter = myFolder.Letters.FirstOrDefault(l => l.Name == "letter1");` Here the `Letters` property isn't in memory yet, but because of lazy loading you can access it as if it were and EF will fetch it – Alexander Derck Feb 19 '16 at 15:23
  • If you tried above example while you disabled lazy loading and you do `var letter = myFolder.Letters.FirstOrDefault(l => l.Name == "letter1");` `letter` would be null even though it exists in your table. – Alexander Derck Feb 19 '16 at 15:24
  • I see, so it's best to decide which way to go according to the transaction's needs. Better keep the default lazy loading and just disable it when it's not helpful or harmful? –  Feb 19 '16 at 15:40
  • 1
    @S.Peter That's what I do :) – Alexander Derck Feb 19 '16 at 15:49
0

I've read that disabling the Lazy load is done by configuring it in the ctor with by setting the EnableLazyLoading property to false and removing virtual key word from the letters list

BOth are not smart. That is equivalent to taking the battery out of your car just to shut down the engine.

Lazy loading ENABLED does not meant it is USED, same with the virtual

What would be the difference if I just use Include(x => x.Lettters) whenever I ask for a folder and keep the Lazy loading enabled?

THat the later would be ABLE to use lazy loading (which you can not after your sabotage).

Include can not be used when Lazy loading is enabled?

Says who? It can totally - in this case lazy loading will simply not happening for already included elements, which gives you freedom to choose lazy loading or not on a case by case basis.

TomTom
  • 61,059
  • 10
  • 88
  • 148
  • And how is lazy loading related to proxy creation? Disabling it disables laziness also? Just to make it clear? Eager loading can and should be used all the time regardless if I keep lazy loading enabled or not? When would I want properties to be lazily loaded? –  Feb 19 '16 at 15:02
0

You can use Include also with lazy load enabled. Not using Include makes the code more clear so usually I use Include only where I have performance issues.
Also, navigation can change during the project life so with lazy load you don't need to remember about it.
And also, you can't use lazy load during serialization otherwise you will probably serialize all the database.

Just for information, Include also often generates very ugly queries (but I never had performance issues).

About parent properties is only usefull for navigation purpose (i.e. you can navigate from a Letter to a Folder then to the Letters of the Folder).

bubi
  • 6,414
  • 3
  • 28
  • 45