泸州北京网站建设,景观设计展板,企业起名,舞台地板一、问题新项目是基于 ABP vNext 框架进行开发的#xff0c;所以我要求为每层编写单元测试。在同事为某个仓储编写单元测试的时候#xff0c;发现了一个奇怪的问题。他的对某个聚合根的 A 字段进行了更新#xff0c;随后对某个导航属性 B 也进行了变更#xff0c;最后通过仓… 一、问题新项目是基于 ABP vNext 框架进行开发的所以我要求为每层编写单元测试。在同事为某个仓储编写单元测试的时候发现了一个奇怪的问题。他的对某个聚合根的 A 字段进行了更新随后对某个导航属性 B 也进行了变更最后通过仓储提供的 UpdateAsync() 方法对变更的数据进行持久化。结果再次查出来的时候发现聚合根的 A 字段倒是更新了但是导航属性 B 的内部字段没有进行变更。例如在下面的实例当中聚合根的 Name 字段变更成功但是导航属性的 Street 字段变更失败了。二、原因数据没有更新到说明问题肯定出在 UpdateAsync 方法内部通过打断点单步步入之后也没发现有什么奇怪的地方是使用的 ABP vNext 提供的默认仓储实现。又在想是否跟实体追踪有关然后看同事写得单元测试代码发现他是先使用的 GetAsync() 方法获取到实体然后手动变更了实体的属性。变更完成之后通过仓储提供的 UpdateAsync() 方法进行更新。看了很久发现它们并不是公用的一个工作单元这就导致 GetAsync() 和 UpdateAsync() 方法内部得到的 DbContext 是不一样的。在 EF Core 内部针对这种情况称之为 Disconnected entities 即断开连接的实体这个时候需要用户手动 Attch 追踪导航属性。三、解决所以有两种解决办法第一种方法是保证使用 GetAsync() 和 UpdateAsync() 方法时它们都处于一个工作单元下例如下面的伪代码。private readonly IUnitOfWorkManager _uowMgr;
private readonly IRepositoryTestUser, 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(琴台路);
}第二种方法变动则要大一些 导航属性没有更新的根本原因是因为在第二个工作单元中没有追踪到这个属性你只需要手动附加该导航属性即可。在下面的例子中我们重写了 UpdateAsync() 方法手动跟踪导航属性也能够达到上述效果。四、参考资料StackOverflow - Entity Framework disconnected graph and navigation propertyMSDN - Disconnected entities