zoukankan      html  css  js  c++  java
  • asp.net core ef core mysql 新增数据并发异常处理

    ---------------------------------------------------------最新更新------------------------------------------------------------------

    经实验,新增出现并发异常的,是由于表中字段设置默认值的引起的。具体原因请看EF生成的sql代码。

    请看异常发生前,ef所执行的sql语句。

    在insert 数据成功后,又执行了一个查询语句,所返回的,正是表中设置默认值的字段。

    这就是导致新增数据出现并发的原因。

    原因如下:

    ef追踪管理实体状态时,假设有个字段type设置有hasDefaultValue(),当前的type字段是没有任何值的,臂如是null。

    当向数据inset数据时,数据库字段设置有默认值是“t”,数据库会将type值null转换为字段默认值t。

    这种情况下,会出现ef管理的实体值与数据库数据值不一致。

    ef core 会将默认值查出来,返回程序中,重新赋值给ef管理的实体,

    在新增的事务尚未结束时,又重新对ef管理的数据有默认值的字段进行修改赋值,就导致了新增数据出现并发的异常。

    ------------------------------------------我是分割线--------------------------------------------------------------------------------------

    net core 2.0发布后,一直想体验下,因种种原因,一直在拖着没进行。

    前阵子公司要加个新的内部管理后台,正好可以用asp.net core来做下,体验下net core的魅力。

    啃过文档后就上手了,一切很顺利。

    直到周五,出现了一个并发异常的问题,本以为可以很快处理掉的,但没想到一直花费了很长时间才解决掉,现在记录下情况,有相同经历的伙伴以后可以参考。

    先上异常截图。

    并发异常

    异常提示:

    Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See

    http://go.microsoft.com/fwlink/?LinkId=527962

    for information on understanding and handling optimistic concurrency exceptions.

    再上代码

     public int Add(BannerView bannerView)
            {
                try
                {
    
                    //sysBanner.ImgUrl = sysBanner.ImgUrl.Contains("http") ? sysBanner.ImgUrl : _programConfig.AliYunOSSUrl + sysBanner.ImgUrl;
                    //sysBanner.CreateDate = DateTime.Now;
                    _banner.Add(new SysBanner {
                        Content = bannerView.Content,
                        CreateDate = DateTime.Now,
                        Del = (int)bannerView.Del,
                        ImgUrl = bannerView.ImgUrl.Contains("http") ? bannerView.ImgUrl : _programConfig.AliYunOSSUrl + bannerView.ImgUrl,
                        Operation = "",
                        Sort = bannerView.Sort,
                        SrcUrl = bannerView.SrcUrl,
                        Title = bannerView.Title,
                        Type = (int)bannerView.Type,
                        //MaterialId = 0,
                        //Parameter = 0,
                        //ShareType = 0
                    });
                    return  _banner.SaveChanges();
                    
                }
                catch (DBConcurrencyException ex)
                {
                    throw;
                }
            }
    

      

            /// <summary>
            /// 新增一条数据
            /// </summary>
            /// <param name="model"></param>
            public void Add(TEntity model)
            {
                var entity=_dbSet.Add(model);
            }
    
    
           public int SaveChanges()
            {
                return _dbContext.SaveChanges();
            }        

    代码特别简单,就是新增一条数据,进行保存,完全没复杂的东西。

    出现并发异常,整个人是蒙逼状态。

    单人进行调试,新增一条数据,自增ID,不存在多用户同时操作,怎么可能出现并发?

    即使出现并发,主键也是自增ID,只会出现多条数据,也不可能是并发异常……并且多个业务模块,其他模块的新增完全是正常的。

    这又是为什么!!!!

    首先就是审视代码,确定没问题……检查依赖注入,没有问题……检查ef生成的sql,没有问题……阅读官方文档,没找到原因……去群里向各位朋友请教,还是无法解决。

    官方文档有一个DBConcurrencyException处理并发异常的,是基于修改和更新的,经试验,无法解决。

    一步一步调试,源码调试,找到几处疑点,经排查都不是引起新增并发的bug。

    重新dbfrist生成model实体,无法解决……删除表,重建表,无法解决。

    似乎走进了死胡同,园子里博问发贴,也没有解决。整个排除过程,说起来都是泪。

    后来就在想,既然底层调用方法都是一样的,那唯一不一样的就是存储的实体,会不会是表结构导致的?

    经过对比出现异常的表与正常的表结构,发现一个不同点,里面有几个字段设置了默认值,还有两个非null字段,而正常操作的那些实体里是没有的。

    尝试取消默认值后,再注释掉dbFirst生成的一行代码HasDefaultValueSql("xxx"),再一运行,居然成功了!!!

    难道是ef core mysql的bug?表不能设置默认值?这似乎不合道理,产品发布这么久了,很多人已经用在生产环境了,不可能出现这么低级的错误吧?

    在园子里博问发贴时,有位园友向我说,默认值的字段,要加.HasDefaultValue()。这种是code first时加的,而我用dbFirst时自动生成的是HasDefaultValueSql("xxx")。

    难道是调用函数不同而产生的bug?

    经过多次实际测试,数据库设置默认值及非null字段是没有问题的。

    问题出在db first生成实体时时自动加的这行代码上HasDefaultValueSql("xxx"),只需要注释掉这些代码,运行就正常。

    .HasDefaultValue()一样会引起新增并发异常,原因未知。

    asp.net core 2.0 

    ef core mysql 

    pomelo.entityFrameworkCore.mySql

    如果有朋友遇到类似问题,可以做为参考。

    至于为什么不能用HasDefaultValueSql("xxx")及.HasDefaultValue(),目前正在研究中,有新发现,会更新文章。

  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/fong/p/8017945.html
Copyright © 2011-2022 走看看