asp.net core 系列之并发冲突
本文介绍如何处理多个用户并发更新同一实体(同时)时出现的冲突 。
主要是两种:一种,检查属性并发冲突,使用 [ConcurrencyCheck] ;另一种,检测行的并发冲突,使用 rowversion 跟踪属性,如果在保存之前有修改,就报错
发生并发冲突的情况:
1.用户导航到实体编辑页面;
2.第一个用户的更改还未写入数据库之前,另一个用户更新同一实体;
此时,如果未启用并发检测,当发生更新时:
最后一个更新优先。即最后一个更新的值保存到数据库。而第一个保存的值将丢失。
举个例子:
1. Jane 访问院系编辑页面,将英语系的预算从 350,000.00 美元更改为 0.00 美元 (第一个用户把金额改为0)
,
2.在 Jane 单击“保存”之前,John 访问了相同页面,并将开始日期字段从 2007/1/9 更改为 2013/1/9。 (在第一个用户保存之前,第二个用户把时间从07年改为13年,注意此时第二个用户看到的金额还不是0)
3.Jane 先单击“保存”,并在浏览器显示索引页时看到她的更改。 (第一个用户先保存,并且可以在浏览器看到他的修改,金额变0,时间不变)
4.John 单击“编辑”页面上的“保存”,但页面的预算仍显示为 350,000.00 美元。 (第二个用户保存,此时的页面的预算显示未350000美元,时间为13年)
其实这个结果取决于并发冲突的处理方式
首先声明,这是一个乐观并发冲突,那么什么是乐观并发冲突呢?
乐观并发冲突允许发生并发冲突,并在并发冲突发生时作出正确的反映。
说了这么多,那么,并发冲突的处理方式呢?
1. 可以跟踪用户已修改的属性,并只更新数据库中相应的列。
这样,当两个用户更新了不同的属性,下次查看时,都将生效。
但是,这种方法,也有一些问题:
- 当对同一个属性进行竞争性更改的话,无法避免数据丢失
- 通常不适用于web应用。它需要维持重要状态,以便跟踪所有提取值和新值。 维持大量状态可能影响应
用性能。 - 可能会增加应用复杂性(与实体上的并发检测相比)。
体现在例子中,就是如果下次有人浏览英语系时,将看到 Jane 和 John
两个人的更改。
2.客户端优先
即客户端的值优先于数据库存储的值。并且如果不对并发处理进行任何编码,将自动进行客户端优先
即John 的更改覆盖 Jane 的更改 。也就是说,下次有人浏览英语系时,将看到 2013/9/1 和提取的值 350,000.00 美元
3.存储优先
这种方式可以阻止在数据库中John的更改。并且可以
- 显示错误消息
- 显示数据的当前状态
- 允许用户重新应用更改。
处理并发
当属性配置为并发令牌时:
- EF Core 验证提取属性后是否未更改属性。 调用 SaveChanges 或 SaveChangesAsync 时会执行此检查。
- 如果提取属性后更改了属性,将引发 DbUpdateConcurrencyException。
数据库和数据模型必须配置为支持引发 DbUpdateConcurrencyException 。
检测属性的并发冲突
可使用 ConcurrencyCheck 特性在属性级别检测并发冲突。 该特性可应用于模型上的多个属性 。[ConcurrencyCheck] 特性
检测行的并发冲突
要检测并发冲突,请将 rowversion 跟踪列添加到模型。
注意:rowversion ,
1.它是 SQL Server 特定的。 其他数据库可能无法提供类似功能。
2.用于确定从数据库提取实体后未更改实体。
数据库生成rowversion序号,该数字随着每次行的更新递增。
在 update 或 delete 命令中,where 子句中包括 rowversion提取值 的判断 。
如果要更新的行已经修改,则 rowversion提取值与现在数据库中rowversion的值不匹配;
update 或 delete 命令不能找到行。引发一个 DbUpdateConcurrencyException 异常
例子
向 Department 实体添加跟踪属性
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ContosoUniversity.Models
{
public class Department
{
public int DepartmentID { get; set; }
[StringLength(, MinimumLength = )]
public string Name { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }
public int? InstructorID { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; } //跟踪属性
public Instructor Administrator { get; set; }
public ICollection<Course> Courses { get; set; }
}
}
Timestamp 特性 指定此列包含在 update 和 delete 命令的 where 子句中。
也可以用 Fluent API 指定跟踪属性:
modelBuilder.Entity<Department>()
.Property<byte[]>("RowVersion")
.IsRowVersion();
以下代码显示更新 Department 名称时由 EF Core 生成的部分 T-SQL:
SET NOCOUNT ON;
UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;
SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = AND [DepartmentID] = @p1;
前面的代码显示包含 RowVersion 的 WHERE 子句。 如果数据库 RowVersion 不等于 RowVersion 参数( @p2
),则不更新行。
@@ROWCOUNT 返回受上一语句影响的行数。 在没有行更新的情况下,EF Core 引发
DbUpdateConcurrencyException
此文主要是为了方便自己记录学习,如有错误,欢迎指正
这里附上参考资料:
https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/concurrency?view=aspnetcore-2.2&tabs=visual-studio
asp.net core 系列之并发冲突的更多相关文章
- asp.net core系列 24 EF模型配置(主键,生成值,最大长度,并发标记)
一.主键 键用作每个实体实例的主要唯一标识符. 使用关系数据库时,这会映射到主键的概念. 还可以配置不是主键的唯一标识符.按照约定,名为 Id 或 <type name>Id 的属性会配置 ...
- asp.net core系列 31 EF管理数据库架构--必备知识 反向工程
一. 反向工程 反向工程是基于数据库架构,生成的实体类和DbContext类代码的过程,对于Visual Studio开发,建议使用PMC.对于其他开发环境,请选择.NET Core CLI工具( ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
- 1.1专题介绍「深入浅出ASP.NET Core系列」
大家好,我是IT人张飞洪,专注于.NET平台十年有余. 工作之余喜欢阅读和写作,学习的内容包括数据结构/算法.网络技术.Linux系统原理.数据库技术原理,设计模式.前沿架构.微服务.容器技术等等…… ...
- asp.net core系列 30 EF管理数据库架构--必备知识 迁移
一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...
- asp.net core系列 40 Web 应用MVC 介绍与详细示例
一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...
- asp.net core系列 39 Web 应用Razor 介绍与详细示例
一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...
- asp.net core系列 38 WebAPI 返回类型与响应格式--必备
一.返回类型 ASP.NET Core 提供以下 Web API Action方法返回类型选项,以及说明每种返回类型的最佳适用情况: (1) 固定类型 (2) IActionResult (3) Ac ...
- asp.net core系列 36 WebAPI 搭建详细示例
一.概述 HTTP不仅仅用于提供网页.HTTP也是构建公开服务和数据的API强大平台.HTTP简单灵活且无处不在.几乎任何你能想到的平台都有一个HTTP库,因此HTTP服务可以覆盖广泛的客户端,包括浏 ...
随机推荐
- 关于java多线程关键字volatile的理解
volatile关键字的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量的值. 使用volition关键字增加了实例变量在多个线程间的可见性.但volition有个致命的缺点就是不 ...
- CSS实现Tab布局
一.布局方式 1.内容与tab分离 <div class="container"> <div class="tab-content"> ...
- SSM-SpringMVC-16:SpringMVC中小论注解式开发之访问方式篇
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 访问方式可以指定,打个比方,你通过get方式进入登陆页面,通过post发送ajax数据库校验或者post提交 ...
- SVG的动态之美-搜狗地铁图重构散记
搜狗地图发布了新版的移动端地铁图,改版初衷是为了用户交互体验的提升以及性能的改善.原版地铁图被用户吐槽最多的是pinch缩放不流畅.无过渡动画.拖拽边界不合理等等,大体上都是交互体验上的问题.实际上原 ...
- sap 内表
内表的目的在ABAP/4中,主要使用表格.表格是R/3系统中的关键数据结构.长期使用的数据存储在关系数据库表格中.关于如何读取和处理数据库表格的详细信息,参见读取并处理数据库表.除了数据库表格,还可以 ...
- php对接微信小程序支付
前言:这里我就假装你已经注册了微信小程序,并且基本的配置都已经好了.注: 个人注册小程序不支持微信支付,所以我还是假装你是企业或者个体工商户的微信小程序,其他的商户号注册,二者绑定,授权,支付开通,就 ...
- Android 不规则封闭区域填充 手指秒变油漆桶
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/45954255: 本文出自:[张鸿洋的博客] 一.概述 在上一篇的叙述中,我们通 ...
- Android推送 百度云推送 入门篇
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27231237 现在app基本都有推送的功能,于是看了下百度云的推送,官方文档和D ...
- Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)
上一篇博客我们已经带大家简单的吹了一下IoC,实现了Activity中View的布局以及控件的注入,如果你不了解,请参考:Android 进阶 教你打造 Android 中的 IOC 框架 [View ...
- Python字符编码与转码
字符编码与转码 注: 该图转自 http://www.cnblogs.com/luotianshuai/p/5735051.html. Python2 解码,编码 #Python2 #-*- codi ...