Entity Framework Pitfalls: Deleting Detached Entities With Required References

It is common practice in O/RMs to delete an entity without actually loading id, just by knowing its id. This saves one SELECT and is great for performance. For example, using Entity Framework Code First:

   1: ctx.Entry(new Project { ProjectId = 1 }).State = EntityState.Deleted;
   2: ctx.SaveChanges();

This, however will fail if there is a [Required] reference (might be defined in fluent configuration, it doesn’t matter) to another entity (many-to-one, one-to-one)! For example, if our Product entity would have something like this:

   1: public class Project
   2: {
   3:     public Int32 ProjectId { get; set; }
   4:  
   5:     [Required]
   6:     public virtual Customer Customer { get; set; }
   7:  
   8:     //...
   9: }

In this case, the required constraint is treated like a concurrency check and the above query will fail miserably. From conversations with the EF team, I understood this is related with some EF internals, which apparently are difficult to change.

There are three workarounds, though:

  1. Remove the required constraint, which may not be appropriate at all;
  2. Load the entity into the context, which, of course, was exactly what we were trying to avoid;
  3. Add a foreign key property for the navigation property.

The third option would be to have something like:

   1: public class Project
   2: {
   3:     public Int32 ProjectId { get; set; }
   4:  
   5:     [Required]
   6:     public virtual Customer Customer { get; set; }
   7:  
   8:     [ForeignKey("Customer")]
   9:     public Int32 CustomerId { get; set; }
  10:  
  11:     //...
  12: }

It really shouldn’t be required to have this foreign key – that’s what navigation properties are meant to replace – but it is. Let’s hope that some future version of EF will fix this.

                             

No Comments

Add a Comment

As it will appear on the website

Not displayed

Your website