Entity Framework 6更新单条记录时全表记录被同步修改问题排查
问题根因
你遇到的全表更新问题是EF6自动生成的MySQL存储过程存在标识符重名冲突导致的:
- 自动生成的
Person_Update存储过程入参名和People表的列名完全一致,而MySQL默认对存储过程内标识符的解析规则是:当参数名与表列名重名时,未限定所属的标识符会优先匹配表列。 - 你存储过程中的
WHEREPersonId= PersonId语句会被MySQL解析为「表的PersonId列等于表的PersonId列」,恒成立,等价于没有WHERE条件,自然会更新全表。 - EF执行日志返回的
result: 2也能佐证这一点:你只更新1条记录,但实际受影响行数为2,和你表的总记录数一致。
修复方案
你可以任选以下任意一种方案修复:
方案1:自定义EF存储过程参数名(推荐)
在OnModelCreating中配置存储过程参数前缀,避免和列名重名,EF会自动生成符合规则的存储过程:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Person>().MapToStoredProcedures(p => p.Update(u => { u.Parameter(pr => pr.PersonId, "p_PersonId"); u.Parameter(pr => pr.Name, "p_Name"); u.Parameter(pr => pr.Lastname, "p_Lastname"); }) ); }
重新生成的存储过程WHERE条件会变成WHERE PersonId = p_PersonId,不会再出现重名冲突。
方案2:修改现有存储过程的标识符限定
如果不想修改EF配置,可以手动修改现有存储过程,明确限定参数所属:
CREATE DEFINER=`root`@`localhost` PROCEDURE `Person_Update`(IN PersonId int,IN Name varchar(255) ,IN Lastname longtext) BEGIN UPDATE `People` SET `Name`=Name, `Lastname`=Lastname WHERE `People`.`PersonId` = `Person_Update`.`PersonId`; END
手动指定等号右侧为存储过程的入参,避免解析冲突。
方案3:关闭存储过程映射
如果不需要强制用存储过程做增删改,直接删除OnModelCreating中的modelBuilder.Entity<Person>().MapToStoredProcedures();代码即可,EF会自动生成UPDATE语句,不会出现重名问题。
内容的提问来源于stack exchange,提问作者h_icon
相关产品推荐
相关产品推荐

