5
votes

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?

2
Could you post a (simplified) copy of your DbContext class?ken2k
@ken2k, I've added it.Denys Denysenko
At first glance, I don't see anything wrong. How are you configuring your ObjectContext? Also, are you using model first approach?ken2k
Sorry, I'm really out of idea now :( Your last screenshot shows pretty straightforward code, no context disposed...etc. I upvoted your question, hopefully someone will find out what's going wrong. Really, everything looks fine to me, I can't tell why proxy are not created.ken2k
I would suggest adding your last screenshot directly in the question, it adds a lot of information about how you access to the context.ken2k

2 Answers

4
votes

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);
0
votes

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.