分类

链接

2011 年 12 月
 1234
567891011
12131415161718
19202122232425
262728293031  

近期文章

热门标签

新人福利,免费薅羊毛

现在位置:    首页 > .NET > 正文
共享办公室出租
LINQ找不到行或行已更改 解决办法
.NET 暂无评论 阅读(6,350)
    刚开始使用Linq,对linq 的更新策略还不是很了解,所以在设计数据库的时候根本就没有考虑到更新检查策略。在插入的时候没有任何问题,更新数据的时候,问题就来了,报错:“System.Data.Linq.ChangeConflictException: Row not found or changed”(找不到行或行已更改)。在网上查了下,这个问题有两种解决办法:一是增加 timestamp(时间戳)列,二是设置主键 IsVersion="true"。我选用了第二种解决办法,OK,更新数据库没有问题了。但是,插入的时候报错:“主键不能插入NULL值”,设置断点,单步跟踪,直到 SubmitChanges()之前,都是有值的,执行SubmitChanges()方法,就报上面的错误。无奈,我决定使用第二种解决办法:设置timestamp列,OK,插入和更新都不报错了。
   下面我来简单说一下Linq的更新检查策略。
   在正常运行状态下,Linq在运行时,会把数据库的数据缓存到实体对象中,所以我们更新数据的时候,并不是直接更新数据库,而是更新缓存中的数据,然后将更改提交到数据库。Linq采用了一种叫做“乐观式并发”的策略。乐观式并发允许任意多的用户随时修改他们自己的一份数据的拷贝。在提交修改时,程序将检查以前的数据是否有所改变。若没有变化,则程序只需保存修改即可。若发生了变化并存在冲突,那么程序将根据实际情况决定是将前一修改覆盖掉,还是把这一次新的修改丢弃,或是尝试合并两次修改。乐观式并发的前一半操作相对来说比较简单。在不需要并发检查的情况下,数据库中使用的SQL语句将类似于如下语法:UPDATE TABLE SET [field = value] WHERE [Id = value]。不过在乐观式并发中,Where子句将不只包含ID列,同时还要比较表中其他各列是否与原有值相同,Linq会默认把除更新字段外的所有字段,作为Update语句中的Where条件。 在调用DataContext的SubmitChanges方法时,LINQ将生成上述Update语句并发送给数据库处理。若这条语句并没有更新数据库中的任意一行,那么DataContext就得知更新过程中产生了冲突,于是抛出“找不到行或行已更改”异常。实际使用中,若用来实现乐观式并发的参数数量过多,可能会导致一些性能上的问题。在这种情况下,我们可以借助UpdateCheck来修改映射规则,只让对象中的一部分属性参与到乐观式并发检查中。在默认情况下,属性的UpdateCheck将设置为Always,即表示LINQ to SQL将用该属性检查乐观式并发。我们可以根据需要将其调整为只在该属性值发生改变时才检查(WhenChanged),或是从不使用该属性进行检查(Never)。
若在数据表中有timestamp 列,其它列(主键除外)的UpdateCheck属性会默认设置为Never,若使用IsVersion作为更新检查依据,则必须在字段上手动设置UpdateCheck.Never属性来避免更新检查,但是如果数据表更新、新增存储过程,需要重新生成dbml的话,你在字段上设置的IsVersion和UpdateCheck.Never都将消失不见,你需要手动重新设置一遍,真是烦不胜烦,所以我推荐使用timestamp作为更新检查依据。

找不到行或行已更改 - 闇丗涴 - 空寂之殇/

有一个数据表Dinner,在LINQ中也会生产一个映射类:Dinner。如果 需要对这个类进行删除或者更新操作,在上下文为断开式更新时会对所有字段都列在Where子句中,以保证更新数据库时是同条记录。如果有字段名不一样,或者 有Null的情况就可能出错。

解决方案:

1、把可为空(NULL)的数据设置默认值,让数据中不出现NULL空值就可以了!

2、将数据映射类中一些不需要进行检查的字段的UpdateCheck属性设置为Never,在类的每个属性上面的特性进行设置,主键(ID)就不要更改


								

============ 欢迎各位老板打赏~ ===========

本文版权归Bruce's Blog所有,转载引用请完整注明以下信息:
本文作者:Bruce
本文地址:LINQ找不到行或行已更改 解决办法 | Bruce's Blog

发表评论

留言无头像?