Home > front end >  Entity Framework Query missing dynamic proxies in some cases
Entity Framework Query missing dynamic proxies in some cases

Time:10-01

Entity framework 6.0 dotnet 4.5

This query collects one record in DB. If it does not exist in DB, creates it and load it.

 using (DBContext sq = new DBContext())
 {
    wfQandA a = sq.wfQandAs.FirstOrDefault(x => x.wfStepID == psid && x.QuestionID == Qid);   
    if (a == null)
    {
          wfQandA a1 = new wfQandA();
          a1.wfStepID = psid;
          a1.QuestionID = Qid;
          a1.OverRiden = false;
          sq.wfQandAs.Add(a1);
          sq.SaveChanges();

          a = sq.wfQandAs.FirstOrDefault(x => x.wfStepID == psid && x.QuestionID == Qid);
      }
      wfStep test= a.wfStep;
}

If record exists in DB, "a" is loaded with dynamic proxies: a ={System.Data.Entity.DynamicProxies.wfQandA_F674B4C0C963114E42A6AF320A5E9E682CF1DA6534BE8FF2F36989FC9BA80D85} I can access all sub tables.

If record does not exist, record is created, and a is queried again. however is this case 'a' is not loaded with dynamic proxy a= {CALMO_DataModels.Models.wfQandA} and all associated sub table are null.

I tried to reload a using SingleOrDefault directly with newly created id, same issue.

What could be causing entity not to load with dynamic proxies?

CodePudding user response:

What could be causing entity not to load with dynamic proxies?

You created the entity with its constructor. And when you query an entity that is already in the change tracker, you get the existing object, not a new one created from the database query.

To manually create a proxy use DbSet.Create

Creates a new instance of an entity for the type of this set. Note that this instance is NOT added or attached to the set. The instance returned will be a proxy if the underlying context is configured to create proxies and the entity type meets the requirements for creating a proxy.

CodePudding user response:

David's answer covers the behaviour. EF will still execute a query for your second fetch attempt, but because it is tracking the instance you newed up, it will return that instance, not a new proxy. It is generally better to eager load related data rather than rely on lazy loading. Lazy Loading should generally be treated as a failsafe rather than default behaviour as it can have significant performance implications.

so:

a = sq.wfQandAs.Include(x => x.wfStep)
    .Single(x => x.wfStepID == psid && x.QuestionID == Qid);

if you wanted the wfStep with the entity, adding Include statements for all related entities.

An alternative would be to tell EF to stop tracking your instance after calling SaveChanges() to ensure the fresh entity proxy is composed:

 using (DBContext sq = new DBContext())
 {
    wfQandA a = sq.wfQandAs.SingleOrDefault(x => x.wfStepID == psid && x.QuestionID == Qid);   
    if (a == null)
    {
          a = new wfQandA();
          a.wfStepID = psid;
          a.QuestionID = Qid;
          a.OverRiden = false;
          sq.wfQandAs.Add(a);
          sq.SaveChanges();
          sq.Entity(a).State = EntityState.Detatched; // Tells DbContext to stop tracking this instance.

          a = sq.wfQandAs.Single(x => x.wfStepID == psid && x.QuestionID == Qid);
      }
      wfStep test= a.wfStep;
}
  • Related