存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。刷新 ObjectStateManager 项。
问题产生的场景可能为:通常会遇到这样的问题,我们打开编辑界面,然后不更改任何内容,然后点保存,基本流程为
1: var detail=db.Table.FirstOrDefault(c=>c.id==1);
2: detail.Content=model.Content;
3: db.SaveChanges();
因为我们没有更改任何内容,所以更改前与更改后的内容是一致的,这时会报出以上错误
其原因是因为MySQL与SQLServer的处理机制不同,如果更新内容与数据库的一致,SQLServer仍然会返回受影响行数为1,但是MySQL则会认为受影响行数为0。
而Entity Framework应该是默认以SQLServer的为准,所以认为如果更新了,但是返回受影响条数为0,则认为是更新不正确
我们处理这个问题有很多方法 ,最笨的应该是在赋值前进行判断,detail.Content是否与model.Content相等,如果相等就不进行赋值。
不过因为EntityFramework是在我们对属性赋值时更新了此属性的State使之标识为Modified或Deleted等 状态,所以我们是可以有更方便的方法来控制这些更新的。
我们可以使用EntityFramework的Context中的SavingChanges这个事件在SaveChanges之前做一些处理:
其基本原理为
if(当前实体已经修改 && 所有属性更改后的值与更改前的值相同){
使之不更新
}
我具体代码实现如下
1: public class EntityFrameworkFix
2: {
3: public static void SavingChanges(object sender, EventArgs e)
4: {
5: var context = sender as ObjectContext;
6: if (context == null) return;
7: var updatedEntites = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
8:
9: foreach (var ose in updatedEntites)
10: {
11: var props = ose.GetModifiedProperties().ToList();
12: int modifyCount = 0;
13: int propCount = props.Count();
14: for (int i = 0; i < propCount; i++)
15: {
16: var prop = props[i];
17: var index = ose.OriginalValues.GetOrdinal(prop);
18: if (ose.OriginalValues.GetValue(index).Equals(ose.CurrentValues.GetValue(index)))
19: {
20: modifyCount++;
21: }
22: }
23: if (modifyCount == propCount)
24: {
25: context.Refresh(RefreshMode.StoreWins, ose.Entity);
26: }
27: }
28: }
29: }
然后我们在我们声明Context时添加如下事件
1: db.SavingChanges += EntityFrameworkFix.SavingChanges;
这样就可以不执行那些赋值了,但值没有变化的Update。
另外,前些天EntityFramework4.1也发布了,但是因为EntityFramework4.1中不再支持SavingChanges所以我们要使用其它方法 来支持,我们可以在DbContext中override ValidateEntity方法来实现这一过程
1: public partial class MyEntities : DbContext
2: {
3: protected override System.Data.Entity.Validation.DbEntityValidationResult ValidateEntity(System.Data.Entity.Infrastructure.DbEntityEntry entityEntry, System.Collections.Generic.IDictionary
最新评论