Entity Framework更新/删除ComputerLabs记录失败,报错影响行数为0
一、删除方法的核心错误:主键参数顺序颠倒
你的DeleteComputerLab方法里,调用db.ComputerLabs.Find(labId, compId, entrance)完全错了!EF的Find方法要求参数顺序严格匹配数据库中复合主键的定义顺序。
从你的建表语句能看到,复合主键的排序是:
CONSTRAINT [PK_ComputerLabs] PRIMARY KEY CLUSTERED ([ComputerId] ASC, [LabId] ASC, [Entrance] ASC)
也就是主键的优先级顺序为:ComputerId → LabId → Entrance
但你调用Find时把labId放在了第一个参数位,这会让EF去查找ComputerId = labId的记录,自然找不到正确的实体。后续尝试删除一个不存在的实体,就会抛出Store update, insert, or delete statement affected an unexpected number of rows (0)异常。
修正后的删除方法:
private void DeleteComputerLab(int compId, int labId, DateTime entrance) { // 严格按照主键定义顺序传递参数:ComputerId, LabId, Entrance var entity = db.ComputerLabs.Find(compId, labId, entrance); if (entity != null) // 先判断实体是否存在,避免空引用 { db.ComputerLabs.Remove(entity); db.SaveChanges(); } }
二、更新方法的两个明显问题
你的RemoveComputerFromLab方法存在两处逻辑漏洞:
未使用参数
compId过滤数据:
方法明明接收了compId参数,但查询条件只过滤了LabId和Exit为空,这会拿到该实验室下所有未退出的电脑记录,而非你要更新的目标电脑。如果实验室有多台未退出的电脑,你修改的会是第一条匹配的记录,完全偏离了初衷。冗余的状态设置:
从数据库查询出来的实体已经被EF上下文跟踪,修改属性后直接调用SaveChanges()即可,不需要手动设置db.Entry(cL).State = EntityState.Modified(这只适用于离线实体)。
修正后的更新方法:
public void RemoveComputerFromLab(int compId, int labId) { // 加入compId过滤,精准定位目标电脑的未退出记录 var targetRecord = db.ComputerLabs.FirstOrDefault(e => e.ComputerId == compId && e.LabId == labId && !e.Exit.HasValue); if (targetRecord != null) { targetRecord.Exit = DateTime.Now; db.SaveChanges(); } }
额外小提示
操作实体前务必先判断是否为null,既能避免空引用异常,也能提前拦截“操作不存在实体”的情况,减少不必要的数据库交互。
内容的提问来源于stack exchange,提问作者O. Nasirov

