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; }

                             

4 Comments

  • 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.

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

  • 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.

  • 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 http://weblogs.asp.net/ricardoperes/archive/2013/05/09/entity-framework-code-first-fluent-validation.aspx and http://weblogs.asp.net/ricardoperes/archive/2013/06/25/pluggable-rules-for-entity-framework-code-first.aspx

Add a Comment

As it will appear on the website

Not displayed

Your website