Entity Framework with MySQL Provider 更新行数为0的Bug

本文将很容易解决的问题搞复杂了,多数情况下将MySql连接字符串中的Use Affected Rows参数设置为true即可。

2012-06-17 作者注。

 

在使用MySQL数据库来做为Entity Framework的Provider时,有时会遇到如下问题:

存储区更新、插入或删除语句影响到了意外的行数(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<object, object> items)
   4:     {
   5:         int wrongCount = 0;
   6:         int allCount = 0;
   7:         if(entityEntry.State== System.Data.EntityState.Modified)
   8:         {
   9:             foreach(var name in entityEntry.OriginalValues.PropertyNames)
  10:             {
  11:                 var prop = entityEntry.Property(name);
  12:                 if (prop.IsModified)
  13:                 {
  14:                     allCount++;
  15:                     if (prop.OriginalValue.Equals(prop.CurrentValue))
  16:                         wrongCount++;
  17:                 }
  18:  
  19:             }
  20:             if (wrongCount == allCount)
  21:                 entityEntry.State = System.Data.EntityState.Unchanged;
  22:         }
  23:         return base.ValidateEntity(entityEntry, items);
  24:     }
  25: }
时间: 2024-10-06 06:25:12

Entity Framework with MySQL Provider 更新行数为0的Bug的相关文章

数据库-Entity framework 对mysql的支持在实体数据模型向导里面没有mysql

问题描述 Entity framework 对mysql的支持在实体数据模型向导里面没有mysql 快折腾我三天,求大神指导指导,有时候新建的项是的,但是是这样的 我明明引用的是mysql的为什么会出现其他的而且还没有mysql的,除了数据库不是最新的其他的中间项都是下载的最新的,求解脱···· 解决方案 是不是引用步骤不对啊,网上各有说辞,我都试过,都不能成功配置. 解决方案二: 新版的不应该这么做·····························

mysql-使用Entity Framework链接Mysql数据库所有浮点型字段无法显示问题

问题描述 使用Entity Framework链接Mysql数据库所有浮点型字段无法显示问题 如题,不知道为何只要是Mysql中使用了浮点型字段,在EF在项目中都无法生成实体字段,不知各位大神有没有遇到过的或是解决方案,十分感谢. 解决方案 看看是不是映射的问题,两边不对应.换成decmal看看

MySQL返回影响行数的测试示例

  found_rows() : select row_count() : update delete insert 注:需要配合相应的操作一起使用,否则返回的值只是1和-1(都是不正确的值) 示例: drop database if exists `mytest`; create database `mytest`; use `mytest`; drop table if exists `MyTestTable`; create table `MyTestTable`(`ID` int ,`N

dbutils 的QueryRunner执行sql语句,返回受影响行数为0的问题?

问题描述 RT:我有个线程,每个周期会执行一次这样的sql语句updateabbottPnd..abt_sms_sendtask_list_historysetabt_status=t.status,abt_status_desc=t.smgstatus,abt_report_time=t.donetime,abt_mobile_type=t.carriertypefromabt_sms_sendtask_list_historyainnerjoin(selecttop5000b.status,

mybatis mysql update 返回影响行数错误

问题描述 mybatis mysql update 返回影响行数错误 数据库有个订单表 有一行数据 order_id=1555(自增主键),有个标记字段order_mark=2 执行语句update t_order set order_mark = 2 where order_id=1555 使用mysql自带的client工具 Query OK 0 rows affected (0.00 sec)Rows matched: 1 Changed: 0 Warnings: 0 使用Navicat

mysql mybatis 执行update 返回影响行数错误

问题描述 mysql mybatis 执行update 返回影响行数错误 文章内容在:http://www.oschina.net/question/1244507_250862 我就不再次编辑了 解决方案 kohana返回db影响的行数,mysql影响的行数(delete,update)----------------------

MySQL &amp;amp; Entity Framework Code First 数据表大小写的问

以前都是使用Linux平台下的MySQL,现在为了调试方便,在开发机上安装了MySQL的Windows版本5.6.10,在使用Entity Framework Code First生成数据库对象时,发现所有的数据表的表名都变成了小写字符,而字段的名称是混合大小写的,这个问题在Linux平台上没有出现过,于是着手弄明白这是肿么一回事. 经过网上搜索,找到这篇文章: Entity Framework with mysql, Table Capitalization issue between lin

看看Entity Framework 4生成的复杂的分页SQL语“.NET研究”句

之前发现Ent上海网站建设ity Framework 4生成的COUNT查询语句问题,今天又发现它生成的分页SQL语句问题,而LINQ to SQL却不存在这个问题. >>> 来看一看,瞧一瞧! 上代码: 看生成的SQL语句: 1. Entity Framework生成的SQL: 一个TOP,三个FROM. 上海闵行企业网站设计与制作 2. LINQ to SQL生成的SQL: 无TOP,两个FROM. 两者的差距一目了然. >>> 再来看一个: 将上面代码中Where

Entity Framework 缓存处理与日志监控

在Kooboo中使用了Entity Framework作为持久化框架,但由于EF1.0并没有提供完整缓存解决方案,一直以来都在为数据缓存而烦脑,在没有找到合适解决方案的情况下,采取了临时的解决办法:直接缓存实体.但是由于Entity实体都是带状态的,并且都与ObjectContext有间接的反向引用,缓存带状态的实体,会造成对象上下文混乱和连接资源的无法被正确释放.因此缓存的Entity实体,首先必须被分离或者重新定义POCO实体来代替Entity实体作为缓存对象.这样一来,所有的缓存实体的关联