Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

Entity Framework Pitfalls – Validation Does Not Load Lazy Properties

In a nutshell: Entity Framework Code First (EFCF) validation does not load lazy properties. If any of these properties is marked as required, and it is not loaded, a validation error will occur.

While I understand the reason – imagine you are saving lots of entities where a required property is not loaded, this will cause lots of accesses to the database just for checking that the required entity exists – I think the way things are is not very productive. I hope the Entity Framework team can come up with a solution, I’ll probably propose something myself.

Imagine you have a class model such as:

   1: public class Parent
   2: {
   3:     public Int32 ParentId { get; set; }
   4:     public virtual ICollection<Child> Children { get; set; }
   5: }
   6:  
   7: public class Child
   8: {
   9:     public Int32 ChildId { get; set; }
  10:     [Required]
  11:     public virtual Parent Parent { get; set; }
  12: }

Say you load a child and make some change:

   1: Child c = ctx.Children.Find(1);
   2: c.SomeProperty = "...";
   3:  
   4: ctx.SaveChanges();

This will throw a DbEntityValidationException, because EFCF will think that the Child instance does not have its Parent property set. This is really annoying and is the source of great frustration.

Of course, there are some workarounds:

  • Explicitly force loading all lazy loaded properties before calling SaveChanges;
   1: var p = c.Parent;
  • Include all lazy loaded properties in the query (best option), such as:
   1: var c = ctx.Children.Where(x => x.ChildId == 1).Include(x => x.Parent).Single();
  • Disable validation at all (not recommended):
   1: ctx.Configuration.ValidateOnSaveEnabled = false;
  • Disable lazy loading globally (also not recommended):
   1: ctx.Configuration.LazyLoadingEnabled = false;
   2: ctx.Configuration.ProxyCreationEnabled = false;
  • Finally, you can remove the required constraint (not good as well):
   1: public virtual Parent Parent { get; set; }

Comments

James Hancock said:

The best way would be to have your FK in there as non-nullable and then the problem is solved because you're testing the thing that really matters and not wasting a ton of SELECT * to test an FK property being set.

# August 28, 2013 8:19 AM

Ricardo Peres said:

James:

What do you mean? By placing a [Required], the foreign key becomes non-nullable...

# August 28, 2013 9:09 AM

Josh Charles said:

A much better solution is to not run validation on your entity models and instead work with business objects (auto-mapper is your friend).  And to turn off lazy loading all together in your context.  It forces your code to be much cleaner and much more explicit.

# August 28, 2013 12:09 PM

Ricardo Peres said:

Josh:

Do you really think disabling lazy loading is a good option?

As for other validation options, I have mentioned them in other posts, see for example weblogs.asp.net/.../entity-framework-code-first-fluent-validation.aspx and weblogs.asp.net/.../pluggable-rules-for-entity-framework-code-first.aspx

# August 28, 2013 12:20 PM