分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

asp.net并发请求导致的数据重复插入问题

发布时间:2023-09-06 02:31责任编辑:白小东关键词:暂无标签

前段时间工作中,有客户反应了系统中某类待办重复出现两次的情况。我核实了数据之后,分析认为是并发请求下导致的数据不一致性问题,并做了重现。其实这并不是一个需要频繁调用的功能,但是客户连续点击了两次,导致出现了并发问题。除了前端优化,这里重点探讨后台方面代码层面的处理,最终解决问题。

一、情景分析

Asp.net程序部署Web服务,是多主线程并发执行的,当多个用户请求进入同一个后台函数时,后进入的请求有可能会获取到非最新状态的数据。

结合我遇到的实际情况举个例子,假设后台函数Func1,先读取表TableA,TableB的数据,进行处理后,存入TableB中,而数据库事务执行会在函数结束前才提交。请求Req1执行Func1提交事务之前,Req2又进入Func1并读取了TableA,TableB的数据,这时Req1执行完成,这就相当于Req2拿到的已经是旧的数据,在旧的数据的基础上再做数据处理操作,结果自然不正确了。

说到这里,你可能还不能想象具体会出现什么问题,而确实这种并发情况在非幂等功能下才会导致数据错误,下面就举实例说明。

二、实例重现

现在有数据表Info,Info2,Info2的数据就是基于Info表数据产生的,两个表都有唯一索引字段-证件号码IdentNo。

函数SyncWork()的功能为:

1,读取Info表和Info2表中共同的IdentNo行数据,将Info表中的其它字段同步到Info2表;

2,读取Info表中有,而Info2表中没有的IdentNo行数据,将这些数据插入Info2表。

表实体代码实现如下:

 1 ????/// <summary> 2 ????/// 信息表 3 ????/// </summary> 4 ????public class Info 5 ????{ 6 ????????public int Id { get; set; } 7 ????????/// <summary> 8 ????????/// 证件号码 9 ????????/// </summary>10 ????????public string IdentNo { get; set; }11 ????????/// <summary>12 ????????/// 姓名13 ????????/// </summary>14 ????????public string Name { get; set; }15 ????????/// <summary>16 ????????/// 爱好17 ????????/// </summary>18 ????????public string Hobby { get; set; }19 ????????/// <summary>20 ????????/// 备注信息21 ????????/// </summary>22 ????????public string Bz { get; set; }23 ????}24 25 ????/// <summary>26 ????/// 信息表227 ????/// </summary>28 ????public class Info229 ????{30 ????????public int Id { get; set; }31 ????????/// <summary>32 ????????/// 证件号码33 ????????/// </summary>34 ????????public string IdentNo { get; set; }35 ????????/// <summary>36 ????????/// 姓名37 ????????/// </summary>38 ????????public string Name { get; set; }39 ????????/// <summary>40 ????????/// 爱好41 ????????/// </summary>42 ????????public string Hobby { get; set; }43 ????????/// <summary>44 ????????/// 创建时间45 ????????/// </summary>46 ????????public DateTime CreateTime { get; set; }47 ????????/// <summary>48 ????????/// 最后修改时间49 ????????/// </summary>50 ????????public DateTime? UpdateTime { get; set; }51 ????????/// <summary>52 ????????/// 评分53 ????????/// </summary>54 ????????public int? Score { get; set; }55 ????}
View Code

 SyncWork()代码实现如下,代码中加入了辅助的输出信息:

 1 ????????public static string SyncWork() 2 ????????{ 3 ????????????StringBuilder sb = new StringBuilder(); 4 ????????????// 5 ????????????int threadId = Thread.CurrentThread.ManagedThreadId; 6 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}.线程Id:{threadId}"); 7 ????????????// 8 ????????????MyDbContext db = new MyDbContext(); 9 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}.db初始化");10 ????????????//新增数据11 ????????????var dataToAdd = db.Info.Where(x => !db.Info2.Select(y => y.IdentNo).Contains(x.IdentNo))12 ????????????????.ToList();13 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}.获取待新增数据{dataToAdd.Count}条");14 ????????????dataToAdd.ForEach(x =>15 ????????????{16 ????????????????var info2 = new Info217 ????????????????{18 ????????????????????IdentNo = x.IdentNo,19 ????????????????????Name = x.Name,20 ????????????????????Hobby = x.Hobby,21 ????????????????????CreateTime = DateTime.Now22 ????????????????};23 ????????????????db.Info2.Add(info2);24 ????????????});25 ????????????//更新原有数据26 ????????????var dataToEdit = db.Info.AsQueryable().Join(db.Info2.AsQueryable(), m => m.IdentNo, n => n.IdentNo, 27 ????????????????(m, n) => ?new28 ????????????????{29 ????????????????????info = m,30 ????????????????????info2 = n31 ????????????????})32 ????????????????.ToList();33 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}获取待更新数据{dataToEdit.Count}条");34 ????????????dataToEdit.ForEach(x =>35 ????????????{36 ????????????????x.info2.Name = x.info.Name;37 ????????????????x.info2.Hobby = x.info.Hobby;38 ????????????????x.info2.UpdateTime = DateTime.Now;39 ????????????});40 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}开始休眠5s");41 ????????????Thread.Sleep(5000);42 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}dbSaveBegin");43 ????????????db.SaveChanges();44 ????????????sb.AppendLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}dbSaveEnd");45 ????????????return sb.ToString();46 ????????}
View Code

--End

asp.net并发请求导致的数据重复插入问题

原文地址:https://www.cnblogs.com/jiujiduilie/p/10328232.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved