简体   繁体   English

如何将部分更新操作从ObjectContext转换为DbContext

[英]How to transition partial update operation from ObjectContext to DbContext

I am using entity framework 5.0. 我正在使用实体框架5.0。 I am in a rocess od changing my app from ObjectContext to DbContext model. 我正在将我的应用程序从ObjectContext更改为DbContext模型。 DbContext should be according to microsoft the recommended approach. DbContext应该根据Microsoft的推荐方法。 I use database forst approach and I have generated model form database. 我使用数据库forst方法,并且已经生成了模型表单数据库。 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,仅用于说明:

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. 我已经注意到,使用DbContext不像ObjectContext那样不支持更新记录。 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. 使用ObjectContext此方法可以正确更新记录。 Using SQL profiler I can see that it generates something like this (greatly simplified!!!) 使用SQL事件探查器,我可以看到它生成了这样的内容(大大简化了!!!)

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

If, however I try to do the same thing in DbContext I get the exception: 但是,如果我尝试在DbContext中执行相同的操作,则会出现异常:

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. 并且没有数据库更新发布到Sql Server。 I guess that DbContext validates all the properties and the property Name is null. 我猜想DbContext会验证所有属性,并且属性Name为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. 显然,ObjectContext无法正确跟踪更改。 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 例如,此链接: 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. 这会产生难看的难以理解的代码,我怀疑lamda表达式在性能上并不算硬。

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? 因此,如何处理简单的实体更新,或者DbContext只是Microsoft死胡同中的又一项没有真正目的的项目?

DbContext doesn't really track changes by watching properties, it compares the values to previously known values. DbContext并不通过监视属性来真正跟踪更改,而是将这些值与以前已知的值进行比较。 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 请参阅带有部分更新的实体框架验证

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: 如果您确定所应用的更改是有效的,或者您具有用于验证它们的自定义代码,则可以完全关闭EF的验证:

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. 只要您按自己的方式做,就可以正常工作:将一个具有已知ID的新实体(也称为存根实体 )附加上,然后修改其属性。 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). EF只会更新它检测到的已被修改的属性(实际上是通过比较原始值和当前值,而不是像ObjectContext那样通过更改通知)。 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). 如果您不想关闭EF的验证,但又不想将单个属性标记为已修改,则我认为可能是一个有用的选择(请Alex的回答引起我的注意)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM