Entity FrameWork乐观并发模式
来源:互联网 发布:达州网络人才网 编辑:程序博客网 时间:2024/06/06 09:40
乐观并发关系到乐观的尝试将entity保存到数据库时,希望entity数据在读取之后,没有被改变过。如果数据被改变过,将会抛出一个异常,而你必须在尝试再次保存前解决这个冲突。本篇涵盖了如何在EntityFrameWork中处理这样的异常。本篇涉及的技术在对于使用Code First或是EF Desinger来创建模型时是同样适用的
本篇并不适合讨论乐观并发,后续内容中假定读者有一定的并发解决方案和通常任务展示模式的知识。
当你使用非关系型数据库(外键并不映射到entity上的一个属性),比使用外键关联时来解决并发问题要困难的多。因此如果你准备实现并发解决方案建议你的应用在你的entity中使用外键。后续所有的例子都假定你使用外键关联
当SaveChanges尝试将一个使用外键关联的entity保存时,检测到一个乐观并发异常时,会抛出一个DbUpdateConcurrencyException异常
数据库优先,使用Reload来解决乐观并发异常
Reload方法用数据库中的值来覆写entity的当前值。entity将会以某种形式会给用户,让他们再次进行改动,并重新保存,例如
using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Update the values of the entity that failed to save from the store ex.Entries.Single().Reload(); } } while (saveFailed); }
模拟并发异常的一个好的方法是在SaveChanges上设置一个断点,然后使用其他数据库工具修改一个entity并保存。你也可以在SaveChanges之前插入一行直接更新数据库的SqlCommand,例如
context.Database.SqlCommand("UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");
DbUpdateConcurrencyException上的Entries方法返回更新失败的entities的DbEntityEntry的实例。这个方法当前对于并发问题是返回单一的值,它也可能返回多个更新异常的值。一个可选的方案就是获取所有的entities,并为他们每一个都执行Reload
以用户优先来解决乐观并发
上面的例子中使用数据库优先,或是称为存储优先的Reload方法,因为在entity中的值被来自于数据的值覆盖。有些时候你可能希望的行为正好相反,使用当前entity中的值来覆盖数据库中的值。这称为用户优先的方式是通过获取当前数据库中的值,并将他们设为entity的original值来实现的
using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Update original values from the database var entry = ex.Entries.Single(); entry.OriginalValues.SetValues(entry.GetDatabaseValues()); } } while (saveFailed); }
Sometimes you may want to combine the values currently in the database with the values currently in the entity. This usually requires some custom logic or user interaction. For example, you might present a form to the user containing the current values, the values in the database, and a default set of resolved values. The user would then edit the resolved values as necessary and it would be these resolved values that get saved to the database. This can be done using the DbPropertyValues objects returned from CurrentValues and GetDatabaseValues on the entity’s entry. For example:
自定义乐观并发异常解决方案
有时候你希望混合当前数据库和当前entity的值。这通常需要一些自定义的逻辑或是界面,例如,你可能要使用表单来呈现包含当前值,数据库值,最终值给用户。用户需要编辑最终值,并将最终值存入数据库。这个步骤可以在entity上使用GetDatabaseValues或是CurrentValues返回的DbPropertyValues对象来完成。例如
using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Get the current entity values and the values in the database var entry = ex.Entries.Single(); var currentValues = entry.CurrentValues; var databaseValues = entry.GetDatabaseValues(); // Choose an initial set of resolved values. In this case we // make the default be the values currently in the database. var resolvedValues = databaseValues.Clone(); // Have the user choose what the resolved values should be HaveUserResolveConcurrency(currentValues, databaseValues, resolvedValues); // Update the original values with the database values and // the current values with whatever the user choose. entry.OriginalValues.SetValues(databaseValues); entry.CurrentValues.SetValues(resolvedValues); } } while (saveFailed); } public void HaveUserResolveConcurrency(DbPropertyValues currentValues, DbPropertyValues databaseValues, DbPropertyValues resolvedValues) { // Show the current, database, and resolved values to the user and have // them edit the resolved values to get the correct resolution. }
使用object来自定义乐观并发异常解决方案
上述代码使用DbPropertyValues 实例来传递当前值,数据库值,和最终值。更方便的方法是使用你的entity实例类型来完成。使用DbPropertyValues的ToObject和SetValues来完成,比如
using (var context = new BloggingContext()) { var blog = context.Blogs.Find(1); blog.Name = "The New ADO.NET Blog"; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Get the current entity values and the values in the database // as instances of the entity type var entry = ex.Entries.Single(); var databaseValues = entry.GetDatabaseValues(); var databaseValuesAsBlog = (Blog)databaseValues.ToObject(); // Choose an initial set of resolved values. In this case we // make the default be the values currently in the database. var resolvedValuesAsBlog = (Blog)databaseValues.ToObject(); // Have the user choose what the resolved values should be HaveUserResolveConcurrency((Blog)entry.Entity, databaseValuesAsBlog, resolvedValuesAsBlog); // Update the original values with the database values and // the current values with whatever the user choose. entry.OriginalValues.SetValues(databaseValues); entry.CurrentValues.SetValues(resolvedValuesAsBlog); } } while (saveFailed); } public void HaveUserResolveConcurrency(Blog entity, Blog databaseValues, Blog resolvedValues) { // Show the current, database, and resolved values to the user and have // them update the resolved values to get the correct resolution. }
原文地址
- Entity FrameWork乐观并发模式
- Entity Framework 乐观并发控制
- Entity Framework 4.1 之六:乐观并发
- Entity Framework 4.1 之六:乐观并发
- Entity Framework Code First实现乐观并发
- 转载]【翻译】Entity Framework 4.1 之六:乐观并发
- Entity Framework 并发处理
- Entity Framework 并发处理
- Entity Framework Repository模式
- MVC5 Entity Framework学习之处理并发
- Entity Framework 处理MySQL,Oracle 并发问题
- 浅析Entity Framework Core中的并发处理
- Entity Framework之Database First生成模式
- Entity Framework之Model First生成模式
- asp.net mvc entity framework模式选择
- Entity Framework入门(1)---开发模式
- ADO.NET Entity Framework中的并发控制 【转载】
- C#综合揭秘——Entity Framework 并发处理详解
- 【Unity3D】Unity脚本执行顺序
- GYM 101128 E.Wooden Signs【Dp】
- 网站图片延时加载2.0
- Ruby操作MongoDB(进阶九)-批量操作Bulk Operations
- TCP/IP checksum 简析
- Entity FrameWork乐观并发模式
- 阿里大于短信服务(短信验证码)
- 存储过程批量插入处理
- MySQL查询时间时间戳
- java线程总结
- Linux上安装MySQL
- 帆软自定义数据源实现一张复杂报表
- Ruby操作MongoDB(进阶十)--文本搜索text search
- 字符组训练--潜伏者