10

My context looks like:

public class ApplicationDbContext: IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
        this.Configuration.LazyLoadingEnabled = true;
    }

    //DbSet properties
}

so, lazy loading is enabled.

I have following class:

public class Home
{
    private ICollection<Slide> _slides;

    [Key]
    [Required]
    public string Name { get; set; }

    [ForeignKey("Header")]
    public int? HeaderID { get; set; }

    //Navigation properties
    public ICollection<Slide> Slides
    {
        get { return _slides ?? (_slides = new List<Slide>()); }
        set { _slides = value; }
    }

    public Content Header { get; set; }
}

Note that both navigation properties Header and Slides are used without virtual keyword. As far as I know when we don't use virtual keyword - properties should load eagerly.

However, when I get my Home entity from database, both my navigation properties are null (but property HeaderID has value).
Even if I switch to this.Configuration.LazyLoadingEnabled = false; - preperties not loaded - they still null.

Here is how I get my data from db (using repository pattern):

public static Home GetHomeComponent(
    this IRepositoryAsync<Home> repository)
{
   var result = repository
       .Query()
       .Select()
       .First();
   return result;
}

I solved my problem with Include properties:

public static Home GetHomeComponent(
    this IRepositoryAsync<Home> repository)
{
   var result = repository
       .Query()
       .Include(x => x.Header)
       .Include(x=>x.Slides)
       .Select()
       .First();
   return result;
}

However it's not convenient for me (since I have too much navigation properties to load).

So, my question is:
I don't use virtual keyword - but why my navigation properties not loading eagerly?
Or I'm doing something wrong? Is there any other way to load my navigation properties without using Include?

Matthew Thurston
  • 720
  • 5
  • 22
user3333333
  • 261
  • 1
  • 3
  • 14
  • if you dont want lazyLoading, why do you set it to true ? – jony89 Jun 01 '14 at 09:52
  • @jony89, because I have many other classes/prepoerties for which I want lazy loading be enabled. I thought `virtual` keyword can control how my data loads - lazy or eagerly, but for some reason it's not working (and my Q is _why it's not working?_)... Btw, as I mentioned in my question, even swithcing to `this.Configuration.LazyLoadingEnabled = false;` doesn't solve my problem - properties still returns `null`. – user3333333 Jun 01 '14 at 09:54

1 Answers1

14

If you don't use the virtual keyword it only means that once you try to access the non-virtual property it wont be loaded from the database but you will get a Null .

It doesn't mean you will have all the properties of the entities populated right away, to populate Slides for E.G in your code, you have to use .Include() - this is eager loading, to load the property by your self before it used .

You can make a generic function that will populate the required properties by the arguments it gets ( using params ) see here for more details :

EntityFramework Eager Load all Navigation Properties

Community
  • 1
  • 1
jony89
  • 5,155
  • 3
  • 30
  • 40
  • Hm..you're right, it was my misunderstanding of meaning of `virtual` keyword.. I've just tried `public virtual Content Header { get; set; }` and it works! As a conclusion, am I right that we use `virtual` keyword for specifying that we want to load this property from db _anyway_ (lazy or eagerly depending on `this.Configuration.LazyLoadingEnabled = true / false;`)? – user3333333 Jun 01 '14 at 10:24
  • 1
    yes, the virtual keyword gives you two things : (1) LazyLoading yes or not... (2) it lets EntityFramework track on your properties ( EF can override the propeties once they are virtual) and this way it optimizing its queries, such as if only one field in a whole entity was change EF will know to update this field only - instead of updating the whole row. – jony89 Jun 01 '14 at 10:32
  • 1
    I have similar problem, although i have the Navigational Entity defined as virtual by EF6 itself through the database first approach, the entity returns null. I even tried the this.configuration.LazyLoadingEnable=true, but that too didn't helped. Can anyone help me here? – Abbas Jun 18 '22 at 19:45