.NET Core 1.1单元测试问题

我们循序渐进,首先从单元测试开始说起,可能其中就有你在.NET Core上进行单元测试会遇到的问题,别着急,不妨一看。我们需要创建.NET Core类库,,如下:

接下来对project.json进行如下修改。

{    "version": "1.0.0-*",    "testRunner": "xunit",    "dependencies": {        "xunit": "2.2.0-beta2-build3300",        "dotnet-test-xunit": "2.2.0-preview2-build1029"},    "frameworks": {        "netcoreapp1.0": {            "dependencies": {                "Microsoft.NETCore.App": {                    "type": "platform",                    "version": "1.0.0"}}}}
}

此时运行单元测试肯定是好使的,由于.NET Core最新为1.1版本此时我们将其版本修改为1.1如下:

"frameworks": {    "netcoreapp1.1": {      "dependencies": {        "Microsoft.NETCore.App": {          "type": "platform",          "version": "1.1.0"}}}}

此时我们写一个测试方法,如下:

    public class Test{[Fact]        public void PassingTest(){Assert.Equal(4, Add(2, 2));}        int Add(int x, int y){            return x + y;}}

此时运行会出现如下dotnet.exe出现异常关闭。

结果让我们大跌眼镜,根本不知道什么地方出错了,此时你再运行单元测试,因为dotnet.exe已经关闭将导致单元测试无法启动,于是乎我们通过 dotnet test 命令来运行看能否得到一点错误提示,结果还是让我找到了原因。

无法加载 Microsoft.DotNet.InternalAbstractions 程序集,此时我们添加该程序集再看看,如下。

"Microsoft.DotNet.InternalAbstractions": "1.0.1-beta-003206"

完美,结果测试通过,至此关于单元测试我们有必要做下结论:官网所给对应的是针对于.net core 1.0版本,运行测试没问题,若是.net core 1.1版本需要添加 Microsoft.DotNet.InternalAbstractions 包。我是从github上才找到解决方案【https://github.com/xunit/xunit/issues/1031】,需要添加上述依赖包才可。

EntityFramework Core 1.1并发导致显式插入主键问题

我们从头讲起,在仓储接口中定义插入Blog的接口,如下:

    public interface IBlogRepository : IEntityBaseRepository<Blog>{        void Create(Blog b);}

然后则是实现该接口了,如下:

    public class BlogRepository : EntityBaseRepository<Blog>,IBlogRepository{        private EFCoreContext _efCoreContext;        public BlogRepository(EFCoreContext efCoreContext) : base(efCoreContext){_efCoreContext = efCoreContext;}        public void Create(Blog b){            try{                using (var transaction = _efCoreContext.Database.BeginTransaction()){_efCoreContext.Blogs.Add(b);_efCoreContext.SaveChanges();transaction.Commit();}}            catch (DbUpdateConcurrencyException ex){...}}}

接下来一切准备就绪,我们来开始进行单元测试,我们开启两个线程来测试看看。

        [Fact]        public void TestEFCore(){            var blog = new Blog(){Name = "Jeffcky",Url = "http://www.cnblogs.com/CreateMyself",Posts = new List<Post>() { new Post() { Title = "a", Content = "ss" } }};            var tasks = new Task[2];            for (int i = 0; i < tasks.Length; i++){tasks[i] = Task.Factory.StartNew(() =>{                    var _contextOptions = new DbContextOptionsBuilder().UseSqlServer("server=WANGPENG;Database=EFCoreDb;Trusted_Connection=True;").Options;                    using (var efcoreContext = new EFCoreContext(_contextOptions)){                        var blogRepository = new BlogRepository(efcoreContext);blogRepository.Create(blog);}});}Task.WaitAll(tasks);}

此时演示结果如下,测试也通过。

当修改测试所开线程,开启如下5个线程时。

 var tasks = new Task[5];

此时将抛出异常,具体演示结果如下:

具体错误信息显示如下:

当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'Blog' 中的标识列插入显式值。

当然这种情况不是一定会发生,有可能开启两个线程不会出现上述以上异常,有可能会抛出异常。为什么会出现上述异常呢,请看如下图。

当一个线程过来时,正常提交肯定是没问题,但是此时该插入的Blog已经被追踪,仅接着又来一个线程,此时Blog中的Id是上一个线程插入的值,所以会导致我们的Id本来主键是自动增长的,而此时Id却有了值出现上述异常。在项目中很难把握这样的情况,也尝试去修改实体的变更追踪的状态,结果依然出现上述问题,最终采用写SQL语句的方式来实现,如果有能够修改变更追踪解决的方案请在评论中给出。在我们项目中,利用SQL语句的方式来解决EF Core的并发,同时开启200个线程没有出任何问题,当然我们的逻辑也还算有一点复杂,所以不用担心EF Core的性能问题,我们更多的是关心业务逻辑。一直在思考怎么通过不写SQL语句的方式去解决这样的并发问题,我能够想到的是既然传过来的实体插入后会被变更追踪,那么我将传过来的参数再实例化一个对象,然后将参数传给它这样应该就能解决问题。

        public void Create(Blog b){            var copyBlog = new Blog() { Name = b.Name, Url = b.Url };            try{                using (var transaction = _efCoreContext.Database.BeginTransaction()){                    _efCoreContext.Blogs.Add(copyBlog);_efCoreContext.SaveChanges();                    var posts = b.Posts.Select(d => new Post(){BlogId = copyBlog.Id,Content = d.Content,Title = d.Title});_efCoreContext.Set<Post>().AddRange(posts);_efCoreContext.SaveChanges();transaction.Commit();}}            catch (DbUpdateConcurrencyException ex){...}}

此时我们开启200个线程来跑跑看看,此时测试通过,如下

我们再来看看数据库是否已经插入200条数据。

这个对于并发导致显式插入主键的问题比较另类的做法,如果有更好的方案请在评论区提出来。

转载于:https://blog.51cto.com/hzz333/1918801

EntityFramework Core并发导致显式插入主键问题相关推荐

  1. boost::core模块检查显式运算符bool测试程序

    boost::core模块检查显式运算符bool测试程序 实现功能 C++实现代码 实现功能 boost::core模块检查显式运算符bool测试程序 C++实现代码 #define BOOST_TE ...

  2. java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)

    java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一) 目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronize ...

  3. 动画总结 Core Animation 贝赛尔曲线 显式动画 隐式动画

    Core Animation 接下来详细介绍下动画的各个属性及作用 fromValue: 动画的开始值(Any类型, 根据动画不同可以是CGPoint.NSNumber等) toValue: 动画的结 ...

  4. java多线程中 锁 的概念的理解,java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)...

    目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...

  5. SQL如何避免重复插入主键

    已知条件:MySQL数据库  存在一张表,表名为teacher,主键为id,表中有4行数据 select * from teacher; 要求:要求使用数据库插入语句往表中插入数据,若需要插入表中的数 ...

  6. 新增一个主键自增长_使用技巧之——MyBatis如何返回插入主键

    优点 mybatis是一种持久层框架,也属于ORM映射.前身是ibatis.相比于hibernatehibernate为全自动化,配置文件书写之后不需要书写sql语句,但是欠缺灵活,很多时候需要优化: ...

  7. 通用mapper自增id mysql_mybatis 通用mapper返回插入主键

    查看地址:http://git.oschina.net/free/Mapper/blob/master/wiki/mapper3/3.Use.md 3.主键策略(仅用于insert方法) 通用Mapp ...

  8. EntityFramework Core解决并发详解

    前言 对过年已经无感,不过还是有很多闲暇时间来学学东西和多陪陪爸妈,这一点是极好的,好了,本节我们来讲讲EntityFramework Core中的并发问题. 话题(EntityFramework C ...

  9. 当 IDENTITY_INSERT 设置为 OFF 时,不能为表中的标识列插入显式值

    {"当 IDENTITY_INSERT 设置为 OFF 时,不能向表 'OrderList' 中的标识列插入显式值"} 对于这个异常可以从两个角度来处理:A:数据库执行语句  B: ...

最新文章

  1. 通过C#实现集合类纵览.NET Collections及相关技术
  2. python白名单验证-Python中XSS白名单过滤的实现
  3. 跨工厂物料状态/特定工厂的物料状态
  4. DDLog-不同颜色打印信息
  5. .htaccess防盗链方法
  6. 【Elasticsearch】Elasticsearch 分布式一致性原理分析:元数据
  7. r 重命名 列名_R-reshape2
  8. 合作︱2018CCF青年精英大会首设科技创业竞赛,快来报名吧!
  9. Linux和qt电子横幅,【Qt】 自定义组件_滚动横幅弹窗对话框字体图标等
  10. eclipse开发java项目_用eclipse 开发java 项目
  11. Jboss 安装配置
  12. Java 的下载安装教程
  13. 计算机文件自动备份到移动硬盘,1个让移动硬盘自动备份的简单方法!
  14. opencv 查找白色图片的一个黑点
  15. 如何将qlv格式视频转换成MP4?这款功能极强的视频格式转换工具不要错过
  16. (附源码)springboot助农电商系统 毕业设计 081919
  17. SpinLock 锁实现
  18. 测试鼠标传感器的软件,鼠标该怎么选择?给大家说下鼠标传感器的差距
  19. 上海徐汇区:幼儿园入园入学攻略大全(招生计划、地段、电话、户籍政策、随迁子女流程)
  20. angular基础创建组件报错Is it missing an @NgModule annotation

热门文章

  1. cad lisp 微盘 程序_使用CAD无法避免的3个坑,你知道怎么绕开吗|AutoCAD断舍离
  2. 查询MySQL中某个数据库中有多少张表
  3. spring freemarker 获取后端的值
  4. 信息系统安全等级保护基本要求_继电保护对电力系统安全运行至关重要,电网对它的基本要求有哪些...
  5. 杨凌职业技术学院计算机专业宿舍,杨凌职业技术学院宿舍条件,宿舍图片和环境空调及分配方法...
  6. 输入分数输出小数C语言,这是把小数转换成分数的程序,可是输入0.6666无限循环...
  7. 在Eclipse中打jar包
  8. 本地虚拟机部署java项目(tomcat8 ,jdk8,VMWare)
  9. 三线压力传感器原理_电喷摩托车进气压力传感器原理与检测
  10. 用户行为分析面面观之一