EF6 lazy loading doesn't work while eager loading works fine

c# entity-framework-6

Question

I updated my app from EF4.1 to EF6 and now I've got lazy loading issue. I used EF6.x DbContext Generator to generate new DbContext. All of the advices from this article are also applied.

  • My classes are public
  • Not sealed, not abstract
  • Have a public constructor
  • Don't implement neither IEntityWithChangeTracker nor IEntityWithRelationships
  • Both ProxyCreationEnabled and LazyLoadingEnabled are set to true
  • Navigation properties are virtual

What also looks wierd to me is that if I explicitly include navigation property with Include("...") it gets loaded.

Simplified version of my POCOs and DbContext:

public partial class Ideation
{
    public Ideation()
    {

    }

    public long Id { get; set; }
    public Nullable<long> ChallengeId { get; set; }

    public virtual Challenge Challenge { get; set; }
}

public partial class Challenge
{
    public Challenge()
    {
        this.Ideations = new HashSet<Ideation>();
    }

    public long Id { get; set; }

    public virtual ICollection<Ideation> Ideations { get; set; }
}

public partial class BoxEntities : DbContext
{
    public TIBoxEntities()
        : base("name=BoxEntities")
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Ideation> Ideations { get; set; }
    public virtual DbSet<Challenge> Challenges { get; set; }
}

Also I tried to set ProxyCreationEnabled and LazyLoadingEnabled explicitly without no luck. The entity isn't loaded as a dynamic proxy as this debug session screenshot shows:

Debug

What else am I missing?

1
5
3/3/2014 6:40:07 PM

Accepted Answer

A situation where this could happen is that the entity you are trying to load with Find is already attached to the context as a non-proxy object. For example:

using (var context = new MyContext())
{
    var ideation = new Ideation { Id = 1 }; // this is NOT a proxy
    context.Ideations.Attach(ideation);

    // other stuff maybe ...

    var anotherIdeation = context.Ideations.Find(1);
}

anotherIdeation will be the non-proxy that is already attached and it is not capable of lazy loading. It even wouldn't help to run a DB query with var anotherIdeation = context.Ideations.SingleOrDefault(i => i.Id == 1); because the default merge option for queries is AppendOnly, i.e. the new entity would only be added if there isn't already an attached entity with that key. So, anotherIdeation would still be a non-proxy.

You can check if the entity is already attached by using Local before you call Find in your GetById method:

bool isIdeationAttached = context.Ideations.Local.Any(i => i.Id == id);
4
3/3/2014 7:00:40 PM

Popular Answer

Per @ken2k's comment, the default for new models starting with EF 4 was to enable lazy loading by default. With EF 1, it was not allowed. If you migrated your model from 1 to 4, it is kept off by default. You would need to modify the context to turn that on.

That being said, you indicate through debugging that it is true. In that case, check your usage scenarios. Is it possible your context has been disposed prior to fetching the child objects. Typically we see this when data binding to the LINQ query where the context is configured in a Using block and the actual iteration doesn't happen until after the using block's scope has passed.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow