在 ABP vNext 中编写仓储单元测试的问题一则

一、问题

新项目是基于 ABP vNext 框架进行开发的,所以我要求为每层编写单元测试。在同事为某个仓储编写单元测试的时候,发现了一个奇怪的问题。他的对某个聚合根的 A 字段进行了更新,随后对某个导航属性 B 也进行了变更,最后通过仓储提供的 UpdateAsync() 方法对变更的数据进行持久化。

结果再次查出来的时候,发现聚合根的 A 字段倒是更新了,但是导航属性 B 的内部字段没有进行变更。例如在下面的实例当中,聚合根的 Name 字段变更成功,但是导航属性的 Street 字段变更失败了。

640?wx_fmt=gif

二、原因

数据没有更新到,说明问题肯定出在 UpdateAsync 方法内部,通过打断点单步步入之后,也没发现有什么奇怪的地方,是使用的 ABP vNext 提供的默认仓储实现。

又在想是否跟实体追踪有关,然后看同事写得单元测试代码,发现他是先使用的 GetAsync() 方法获取到实体,然后手动变更了实体的属性。变更完成之后,通过仓储提供的 UpdateAsync() 方法进行更新。

看了很久发现它们并不是公用的一个工作单元,这就导致 GetAsync() 和 UpdateAsync() 方法内部得到的 DbContext 是不一样的。在 EF Core 内部针对这种情况,称之为 Disconnected entities 即断开连接的实体,这个时候需要用户手动 Attch 追踪导航属性。

三、解决

所以有两种解决办法,第一种方法是保证使用 GetAsync() 和 UpdateAsync() 方法时,它们都处于一个工作单元下,例如下面的伪代码。

private readonly IUnitOfWorkManager _uowMgr;
private readonly IRepository<TestUser, Guid> _repository;[Fact]
public async Task Resolve1()
{var entityId = Guid.NewGuid();await _repository.InsertAsync(new TestUser{Id = entityId,Name = "张三",Address = new TestUserAddress{City = "成都市",Street = "春熙路"}});using (var outerUow = _uowMgr.Begin()){var entity = await _repository.GetAsync(entityId);entity.Name = "李四";entity.Address.Street = "琴台路";await _repository.UpdateAsync(entity);await outerUow.CompleteAsync();}var result = await _repository.GetAsync(entityId);result.Name.ShouldBe("李四");result.Address.Street.ShouldBe("琴台路");
}

640?wx_fmt=png

第二种方法变动则要大一些, 导航属性没有更新的根本原因,是因为在第二个工作单元中没有追踪到这个属性,你只需要手动附加该导航属性即可。在下面的例子中,我们重写了 UpdateAsync() 方法,手动跟踪导航属性,也能够达到上述效果。

640?wx_fmt=png

四、参考资料

  • StackOverflow - Entity Framework disconnected graph and navigation property

  • MSDN - Disconnected entities

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313734.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP协议——三次握手与四次关闭

1. TCP协议基础 网络编程基础见&#xff0c;传送门 TCP是面向连接的&#xff0c;无论哪一方向另一方发送数据之前&#xff0c;都必须先在双方之间建立一条连接。 在TCP/IP协议中&#xff0c;TCP协议提供可靠的连接服务&#xff0c;连接是通过三次握手进行初始化的。 三次握手…

在 .NET Core 3.0 中实现 JIT 编译的 JSON 序列化,及一些心得与随想

源码&#xff1a;https://github.com/Martin1994/JsonJitSerializerNuGet&#xff1a;https://www.nuget.org/packages/MartinCl2.Text.Json.Serialization/简介&#xff1a;Just-in-time 编译的 JSON 序列化&#xff0c;基于 System.Text.Json.NET Core 3.0 即将正式发布&…

E. Company(Codeforces Round #520 (Div. 2))

E. Company 给定一颗有nnn个节点的树&#xff0c;有mmm次询问&#xff0c;每次询问给定[l,r][l, r][l,r]&#xff0c;我们可以选择删除其中的一个点ppp&#xff0c;然后找到一个深度最深的rtrtrt&#xff0c;使得剩下的点都在rtrtrt的子树上。 考虑对编号为[l,r][l, r][l,r]中…

TCP协议——流量控制和拥塞控制

** 一、流量控制 ** 1.1 什么是流量控制 Sender won’t overflow receiver’s buffer by transmitting too much, too fast. &#xff08;防止发送方发的太快&#xff0c;耗尽接收方的资源&#xff0c;从而使接收方来不及处理&#xff09; 1.2 流量控制的一些知识点 &#x…

征集.NET中国峰会议题

月初做的调查《》&#xff0c;参与人数576人&#xff0c;愿意参与分享.NET Core经验的142人&#xff0c;今天发起分会场主题演讲和闪电演讲议题.2014年微软组织成立.NET基金会&#xff0c;微软在成为主要的开源参与者的道路上又前进了一步。2014年以来已经有众多知名公司加入.N…

TCP协议——粘包与拆包

TCP的基础 TCP协议基础&#xff0c;传送门 TCP协议流量控制&#xff0c;传送门 1.1 什么是TCP粘包/拆包 TCP是个“流”协议&#xff0c;所谓流&#xff0c;就是没有界限的一串数据。大家可以想想河里的流水&#xff0c;是连成一片的&#xff0c;其间并没有分界线。TCP底层并…

B. Lynyrd Skynyrd(倍增 + 区间最小值)

B. Lynyrd Skynyrd&#xff08;segment tree redouble&#xff09; 给定一个长度为nnn的排列ppp&#xff0c;一个长度为mmm的数组aaa&#xff0c;有mmm次询问&#xff0c;每次询问给定l,rl, rl,r&#xff0c;问在数组aaa中是否存在一个子序列构成的串是ppp的循环位移串&#…

你的通勤时间都去哪了?

大家好&#xff0c;我是Z哥。今天我来唠叨一下。最近无意间看到一份报告&#xff0c;关于我们职场人士上下班通勤时间的。有时候想想也挺无奈的&#xff0c;我们越想去发达一些的城市打拼&#xff0c;反而越被通勤这种琐碎的事情给耽误更多的奋斗时间。但是没办法&#xff0c;在…

规模化敏捷必须SAFe

引子&#xff1a;规模化敏捷转型从来不是一件容易的事情。当只有1-2个敏捷团队进行协同的时候&#xff0c;计划和工作同步是可控的。团队和产品负责人互相聊一聊&#xff0c;基本就能搞清楚需要做什么&#xff0c;一个简单的SOS架构&#xff08;Scrum of Scrums&#xff09;就能…

http1.0 http1.1 http2 之间的区别

一、HTTP基础 1.1 HTTP定义 HTTP协议&#xff08;HyperTextTransferProtocol&#xff0c;超文本传输协议&#xff09;是用于从WWW服务器传输超文本到本地浏览器的传输协议。 1.2 HTTP发展史 1.3 HTTP1.0 早先1.0的HTTP版本&#xff0c;是一种无状态、无连接的应用层协议。 …

B. Alyona and a tree(dsu on tree + bit)

B. Alyona and a tree&#xff08;dsu on tree bit&#xff09; 给定一颗以111号节点为根的树&#xff0c;每个点有点权aia_iai​&#xff0c;边有边权&#xff0c;如果vvv控制了点uuu&#xff0c;当且仅当uuu是vvv的子树中的节点且dis(u,v)≤audis(u, v) \leq a_udis(u,v)≤…

HTTP get post put delte等

超文本传输协议&#xff08;HTTP, HyperText Transfer Protocol&#xff09;是一种无状态的协议&#xff0c;它位于OSI七层模型的传输层。HTTP客户端会根据需要构建合适的HTTP请求方法&#xff0c;而HTTP服务器会根据不同的HTTP请求方法做出不同的响应。 HTTP版本与HTTP请求方…

P1600 [NOIP2016 提高组] 天天爱跑步(线段树合并,lca)

P1600 [NOIP2016 提高组] 天天爱跑步 给定一颗有nnn个点的树&#xff0c;有mmm个人在树上移动&#xff0c;第iii个人从sis_isi​点&#xff0c;移动到tit_iti​点&#xff0c;且他们按照最短路移动&#xff0c;每秒移动一条边的距离&#xff0c; 点iii在wiw_iwi​时刻有一个观…

漫画:程序员一时单身一时爽,一直单身...有点惨

1妹子没吃早饭早啊敲哥&#xff0c;你在吃早饭啊嗯啊&#xff0c;你吃了吗&#xff1f;没呢&#xff0c;早上实在是太赶了&#xff0c;没来得及嗯...那我还是换个地方吃吧免得馋着你。。。2代码重要还是女朋友重要女朋友能哄好&#xff0c;代码能哄好吗&#xff1f;写代码是赚钱…

P3564 [POI2014]BAR-Salad Bar(ST表 + 二分)

P3564 [POI2014]BAR-Salad Bar 给定一个长度为nnn的数组&#xff0c;里面元素只有111跟−1-1−1&#xff0c;问选出一个长度为lenlenlen的区间使得&#xff0c;这个区间的前缀和时刻大于零&#xff0c;后缀和时刻大于零&#xff0c;输出最大长度lenlenlen&#xff0c; 考虑枚…

【招聘(深圳)】迈瑞招.NET 开发Leader和PM

应用开发管理&#xff08;开发leader&#xff09;工作职责&#xff1a;1.负责应用开发小组管理&#xff1b;2.协助项目经理制定项目计划和控制项目进度&#xff1b;3.评估用户需求&#xff0c;设计解决方案、系统功能&#xff0c;并带领开发小组进行交付&#xff1b;4.对开发过…

Java RMI,Socket,HttpClient

Java RMI Java远程方法调用&#xff08;Java Remote Method Invocation&#xff09; 是Java编程语言里&#xff0c;一种用于实现远程过程调用的应用程序编程接口。 它使客户机上运行的程序可以调用远程服务器上的对象。 远程方法调用特性使Java编程人员能够在网络环境中分布操…

E. Sign on Fence(整体二分 + 线段树维护区间最大连续 1 的个数)

E. Sign on Fence 给定一个长度为nnn的数组aaa&#xff0c;1≤ai≤1091 \leq a_i \leq 10 ^ 91≤ai​≤109&#xff0c;有mmm次询问&#xff0c;每次给定l,r,kl, r, kl,r,k&#xff0c;要我们在[l,r][l, r][l,r]区间内找到一个长度为kkk的区间&#xff0c;使得区间最小值最大&…

AutoMapper多个对象映射到一个Dto对象

一、定义源映射对象为了体现AutoMapper映射特性&#xff0c;在SocialAttribute中的Name属性没有定义在People中&#xff0c;People的Ear属性也不存在与SocialAttribute和PhysicalAttribute中。代码如下&#xff1a;二、注入AutoMapper例子中使用的IOC容器是Autofac&#xff0c;…

cookie 与 session

1 背景介绍 什么是会话&#xff1f; 用户打开一个浏览器, 点击多个超链接, 访问服务器多个web资源, 然后关闭浏览器, 整个过程称之为一个会话。我们知道&#xff0c;HTTP协议是一种"无状态"协议&#xff0c;客户浏览器与服务器建立连接&#xff0c;发出请求&#x…