静坐常思己过,闲谈莫论人非,能受苦乃为志士,肯吃亏不是痴人,敬君子方显有德,怕小人不算无能,退一步天高地阔,让三分心平气和,欲进步需思退步,若着手先虑放手,如得意不宜重往,凡做事应有余步。持黄金为珍贵,知安乐方值千金,事临头三思为妙,怒上心忍让最高。切勿贪意外之财,知足者人心常乐。若能以此去处事,一生安乐任逍遥。

ChangeConflictException:Row not found or changed 找不到行或行已更改

作者:大鹏 发布于:2012-5-11 17:25 Friday 分类:Asp.Net 2.0

产生此异常,主要是Linq缓存数据和实际数据库数据不一致的情况造成。解决次问题的情况,主要有几种:

    1.比较简单的方法,不使用Linq提供的SubmitChanges()方式提交更改,而直接执行SQL语句,例

      db.ExecuteCommand("Update [dbo].[LinqTest] SET Age=25 Where ID = @p0", 1);

    这样虽然比较方便,但是感觉又回到了直接写SQL的时代,毕竟Linq to SQL的目的,就是为了让我们看不见SQL,避免写复杂的SQL语句,而直接操作实体对象,这样也可以避免程序可读性差、不便于维护。所以除非万不得已,还是不太推荐使用此方法。

    2.参考MSDN的资料,采用Linq提供的解决更新冲突的方法,在异常中捕获冲突,然后手动解决冲突:

try
{
    db.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);
}
catch (System.Data.Linq.ChangeConflictException ex)
{
    foreach (System.Data.Linq.ObjectChangeConflict occ in db.ChangeConflicts)
    {
         //以下是解决冲突的三种方法,选一种即可

        // 使用当前数据库中的值,覆盖Linq缓存中实体对象的值
        occ.Resolve(System.Data.Linq.RefreshMode.OverwriteCurrentValues);
        
        // 使用Linq缓存中实体对象的值,覆盖当前数据库中的值
        occ.Resolve(System.Data.Linq.RefreshMode.KeepCurrentValues);
        
        // 只更新实体对象中改变的字段的值,其他的保留不变
        occ.Resolve(System.Data.Linq.RefreshMode.KeepChanges);
    }

    // 这个地方要注意,Catch方法中,我们前面只是指明了怎样来解决冲突,这个地方还需要再次提交更新,这样的话,值   
 //才会提交到数据库。
    db.SubmitChanges();
}
3. 这个方法也比较简单,也即MSDN中所说的Pessimistic Concurrency Control  。 我们可以来设定哪些字段需要放入Where条件,哪些字段不需要,这样就可以控制更新时候的条件匹配尺度。具体做法,就是在Linq to SQL Designer中,把一些字段的UpdateCheck属性设置为Never,这样,这些字段在更新的时候,就不会再出现在Where条件中了。其实比较推荐的做法,就是在表中设立主键,因为更新的时候,只要把主键作为Where条件,就可以单独的确立一行数据了。把除主键外的字段属性中UpdateCheck设置为Never即可。


标签: linq

et_highlighter
发表评论 »本文目前尚无任何评论

发表评论

干净网络从你做起,切勿黏贴小广告