0

I am using entity framework 5.0. I am in a rocess od changing my app from ObjectContext to DbContext model. DbContext should be according to microsoft the recommended approach. I use database forst approach and I have generated model form database. But, at a very first simple task there is a problem. Namely simple update of a record is broken.

Let's have a simple table Item, for ilustration only:

Item
(
    ItemId int NOT NULL,    -- Primary key
    Name nvarchar(50) NOT NULL,
    Description NVARCHAR(50) 
)

I have noticed that using DbContext does not support updating a record not as ObjectContext does. In my application I have a simple update method.

public void UpdateItem()
{
      MyContext context = new MyContext();
      Item item = new Item();
      item.ItemId = 666;
      context.Items.Attach(item); 
      // From this point onward EF tracks the changes I make to Item
      Item.Description = "Some description";
      context.SaveChanges();
}

Using ObjectContext this method correctly updates a record. Using SQL profiler I can see that it generates something like this (greatly simplified!!!)

 UPDATE Item
 SET Description = 'Some description'
 WHERE ItemId = 666

If, however I try to do the same thing in DbContext I get the exception:

System.Exception: Items.aspx.cs - logged from CustomError() ---> System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
   at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
   at System.Data.Entity.DbContext.SaveChanges()

And no database UPDATE is issued to Sql server. I guess that DbContext validates all the properties and the property Name is null. This by design. I do not intend to modify it, I do not even know what is it and I do not need to know what is it. Only the property Description was changed. Clearly ObjectContext does not track changes correctly. How can this problem be resolved?

I have researched the issue and found the something on updating records. For example this link: https://stackoverflow.com/a/15339512/4601078

db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();

But this is horrible code. For every property on should add a line like:

entry.Property(e => e.Email).IsModified = true;

This produces ugly unreadable code, an I suspect lamda expression are not stelar in performance.

Even worse are those who propose to make a roundtrip to DB to fetch existing records with all properties populated, update it and the save changes. This is a no go with regard to performance.

So, how to tackle with simple entity updates or is this DbContext just another item in microsofts collection of dead ends which serve no real purpose?

Community
  • 1
  • 1
f470071
  • 1,527
  • 3
  • 18
  • 30

2 Answers2

1

DbContext doesn't really track changes by watching properties, it compares the values to previously known values. And validation always works on the entire entity so the only real choice if you want to do things this way is to disable validation during this operation. See Entity Framework validation with partial updates

Community
  • 1
  • 1
Alex Paven
  • 5,539
  • 2
  • 21
  • 35
  • I know it is a validation exception. It is just that validation itself (or tracking) is wrong. – f470071 May 07 '17 at 10:28
  • Right sorry, updating answer. – Alex Paven May 07 '17 at 10:29
  • Hmmm. The link you provided might be onto something with the answer that suggests using dbContext.Configuration.ValidateOnSaveEnabled = false. Although not a solution it is at least a workaround. I believe the modified properties should still be validated. But it is a workaround and I do my validation in code beforehand of updating. Upvoted for providing the half useful link and a search phrase "partial update". – f470071 May 07 '17 at 11:45
  • Half useful? Those are pretty high standards. But you might want to read all the answers to that question, there's also the option of removing the validation errors for unchanged properties after the fact (still not ideal but oh well). – Alex Paven May 07 '17 at 11:54
0

If you know for sure that the changes you apply are valid, or you have custom code to validate them, you can turn off validation by EF altogether:

db.Configuration.ValidateOnSaveEnabled = false;

This works OK as long as you do it your way: attach a new entity with a known Id (aka a stub entity) and then modify its properties. EF will only update the properties it detects as having been modified (indeed by comparing original and current values, not, as ObjectContext did, by change notifications). You shouldn't mark the entity itself as modified.

If you don't want to turn off EF's validation, but neither want to mark individual properties as modified, I think this could be a useful alternative (brought to my attention by Alex's answer).

Community
  • 1
  • 1
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291