`
wodamazi
  • 浏览: 1416464 次
文章分类
社区版块
存档分类
最新评论

在LINQ to SQL中处理“更新已被其它用户删除对象”的错误

 
阅读更多

在LINQ to SQL中处理“更新已被其它用户删除对象”的错误

在多用户条件下,当你正在修改一条记录时,很有可能另一个用户已把此记录删除。这时,等你修改完毕向数据库提交请求时,会出现“更新已被其它用户删除对象”的错误。

在LINQ to SQL中,所有本次数据更改冲突都被记录到DataContext.ChangeConflicts集合中。

通过遍历这个集合,可以知道引发冲突的原因。

多用户条件下引发数据更改冲突的原因主要有两种:

1更新已被其它用户更新的对象

2更新已被其它用户删除的对象

对于上述两种状况,LINQ to SQL采取了不同的处理方法。

对于第1种情况,LINQ to SQL的DataContext.ChangeConflicts集合对象提供了一个“ResolveAll(更新模式)”方法,最常用的是以下这个形式:

        //数据更新冲突时,将我的值与其他用户提交的值合并,但我修改过的值拥有最高优先级

context.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);

另两种更新冲突处理策略是:

(1) KeepCurrentValues即我的值最优先,不管我改过没有,一律用我的值覆盖对应的数据库值来解决此冲突。

(2)OverwriteCurrentValues 用数据库中的当前值全面取代我现在的值,放弃我做的修改。

选择好合适策略调用ResolveAll()后,再次调用DataContext.SubmitChanges()方法将会成功更新数据库。

对于第2种情况(“更新已被其它用户删除的对象”),LINQ to SQL的处理比较另类:

如果你调用ResolveAll(更新策略)方法,LINQ to SQL仅是简单地将与此对应的冲突对象(ObjectChangeConflict类型)的IsResolve属性设置为True,其结果是LINQ to SQL将不再尝试更新此对象!


换句话说:你调用ResolveAll(更新策略)方法后,LINQ to SQL认为你不打算处理这个已被其它用户删除的对象,就将其打入“冷宫”,不再理会。

现在有一个问题:

如果我想当“更新已被其它用户删除的对象”这一现象出现时,重新向数据库插入此对象,怎么办?

除非采用序列化方法,否则LINQ to SQL不允许将一个实体对象分离出来。但我们可以克隆一个新对象再将其插入到Table<entity>中。然后,将“更新已被其它用户删除的对象”对应的冲突对象设置为“已解决”状态。

以下代码片断来自于一个Windows Form应用程序:

     try
{
context.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch (ChangeConflictException)
{
foreach (ObjectChangeConflict occ in context.ChangeConflicts)
{
//如果其它用户已删除此实体对象对应的数据库记录

if (occ.IsDeleted)
{

         //克隆一个新实体对象
Book newbook = CloneBook(book);
//下次提交时,将插入新对象到Book表中
context.Book.InsertOnSubmit(newbook);
//通知DataContext不再处理此已被其他用户删除数据库记录的实体对象
occ.Resolve();
}

}

//普通的更新冲突,则将我的值与其他用户提交的值合并以解决冲突

context.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
//再次提交
context.SubmitChanges(ConflictMode.FailOnFirstConflict);

}
catch (Exception ex)
{

MessageBox.Show(ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Error);

}

上述模板代码中,context代表DataContext对象,Book是数据库中的表,LINQ to SQL会为它生成同名的实体类。

使用LINQ to SQL更新数据库需要有几个注意事项:

1 当数据表间有主键外键关联时,注意在数据库中将这个关联关系设置为层叠更新与删除。否则, SQL Server会阻止你删除主表记录。除非你一条条地将从表相关记录删除干净后才能删除主表记录。

对应地,如果你要删除某LINQ to SQL实体类对象,但这个对象还包容着相关联的子实体类对象时,一旦尝试向数据库提交更改,而数据库中没有将这个关联关系设置为层叠更新与删除,则LINQ to SQL将自动回滚操作,一条记录也删除不了!其原因是DataContext.SubmitChange()方法默认启动了一个事务,一出现异常则自动回滚。

2 克隆有主键外键关联的实体对象时,注意要一并克隆其所包容的子对象,而不要简单地赋值,那是“对象引用复制”而非“对象本身数据的复制”。具体来说,就是new一个新对象,然后逐个地把老对象的值赋给新对象,这个过程可能会递归好几层。最简单的方法是将原对象序列化到一个内存流中,然后从内存流中反序列化以实现对象的完全克隆。

3 如果需要获取数据库最新数据,可以调用DataContext.Refresh()方法,或者最简单的,直接向数据库发送一个新的LINQ查询,然后更新界面即可(推荐使用数据绑定),后面这个方法最简单可靠。

多用户环境下数据库的记录的存取冲突是一个令人头痛的问题,需要仔细地处理各种情况,这篇短文期望对大家有点帮助。

由于本人对LINQ to SQL技术研究与应用不深,因此,如本文有错,敬请朋友指出。

分享到:
评论

相关推荐

    ASP.NET 控件的使用

    16.1.4 绑定到LINQ to SQL查询 502 16.1.5 绑定到Web服务 503 16.2 使用ObjectDataSource控件与参数 506 16.2.1 使用不同的参数类型 509 16.2.2 作为参数传递对象 511 16.3 使用ObjectDataSource控件分页、排序和...

    ASP.NET.4揭秘

    20.3.5 使用linq to sql进行删除754 20.3.6 动态查询755 20.3.7 调试linq to sql759 20.4 创建自定义的linq实体基类761 20.4.1 使用实体基类762 20.4.2 使用entitybase类执行标准数据访问操作762 20.4.3 用...

    ASP.NET4高级程序设计第4版 带目录PDF 分卷压缩包 part1

    书中还深入讲述了其他ASP.NET图书遗漏的高级主题,如自定义控件的创建、图像处理、加密等。此外,《ASP.NET 4高级程序设计(第4版)》专门提供了两章的内容来教你如何用Ajax 技术制作快速响应的页面,以及如何使用微软...

    ASP.NET3.5从入门到精通

    9.4.2 使用Command 对象删除记录 9.4.3 使用DataSet 数据集删除记录 9.5 使用存储过程 9.5.1 存储过程的优点 9.5.2 创建存储过程 9.5.3 调用存储过程 9.6 ASP.NET 数据库操作实例 9.6.1 制作用户界面(UI) 9.6.2 ...

    ASP.NET 3.5 开发大全word课件

    这是整部学习资料 由于太大第一章免费供应给大家 在我的上传资源中 如果觉得还不过希望大家给个好评 当然具体本书的作者就不深究了把! 第1章 认识ASP.NET 3.5 1.1 什么是ASP.NET 1.1.1 .NET历史与展望 1.1.2 ASP...

    ASPNET35开发大全第一章

    9.4.2 使用Command对象删除记录 9.4.3 使用DataSet数据集删除记录 9.5 使用存储过程 9.5.1 存储过程的优点 9.5.2 创建存储过程 9.5.3 调用存储过程 9.6 ASP.NET数据库操作实例 9.6.1 制作用户界面(UI) 9.6.2 使用...

    ASP.NET 3.5 开发大全11-15

    9.4.2 使用Command对象删除记录 9.4.3 使用DataSet数据集删除记录 9.5 使用存储过程 9.5.1 存储过程的优点 9.5.2 创建存储过程 9.5.3 调用存储过程 9.6 ASP.NET数据库操作实例 9.6.1 制作用户界面(UI) 9.6.2 使用...

    ASP.NET 3.5 开发大全

    9.4.2 使用Command对象删除记录 9.4.3 使用DataSet数据集删除记录 9.5 使用存储过程 9.5.1 存储过程的优点 9.5.2 创建存储过程 9.5.3 调用存储过程 9.6 ASP.NET数据库操作实例 9.6.1 制作用户界面(UI) 9.6.2 使用...

    ASP.NET 3.5 开发大全1-5

    9.4.2 使用Command对象删除记录 9.4.3 使用DataSet数据集删除记录 9.5 使用存储过程 9.5.1 存储过程的优点 9.5.2 创建存储过程 9.5.3 调用存储过程 9.6 ASP.NET数据库操作实例 9.6.1 制作用户界面(UI) 9.6.2 使用...

Global site tag (gtag.js) - Google Analytics