[英]Exception when I try to update graph using Entity Framework Core with AutoMapper
I get an exception when I try to update graph. 尝试更新图形时出现异常。 I use Automapper to map DTOs to my entities, then I check if my object already exists in the database before I do the update operation.
我使用Automapper将DTO映射到我的实体,然后在执行更新操作之前检查数据库中是否已存在我的对象。
When I call dbContext.Update
, I get this exception 当我调用
dbContext.Update
,出现此异常
The instance of entity type 'Order' cannot be tracked because another instance with the same key value for {'OrderId'} is already being tracked.
无法跟踪实体类型“订单”的实例,因为已经跟踪了另一个具有相同“ {'OrderId'}”键值的实例。 When attaching existing entities, ensure that only one entity instance with a given key value is attached.
附加现有实体时,请确保仅附加一个具有给定键值的实体实例。 Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.'
考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值。
My code: 我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using EFCoreIssue;
using EFCoreIssue.Dtos;
using EFCoreIssue.Models;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace EFCoreIssue_Tests
{
public class OrdersTests
{
private readonly OrderRepository _orderRepository;
public OrdersTests()
{
_orderRepository = new OrderRepository(new OrdersDbContext());
Mapper.Initialize(cfg => cfg.CreateMap<OrderDto, Order>());
}
[Fact]
public async void Should_Update_Customer_Successfully()
{
//Arrange
var order = new Order
{
Description = "Test Order",
OrderLines = new List<OrderLine>
{
new OrderLine {ProductId = 1, Quantity = 1}
}
};
using (var dbContext = new OrdersDbContext())
{
dbContext.Orders.Add(order);
await dbContext.SaveChangesAsync();
}
//Act
var orderDto = new OrderDto
{
Description = "Test Order 2",
OrderLines = new List<OrderLineDto>
{
new OrderLineDto {OrderLineId = order.OrderLines[0].OrderLineId, ProductId = 2, Quantity = 2}
},
OrderId = order.OrderId
};
await _orderRepository.UpdateAsync(Mapper.Map<Order>(orderDto));
//Assert
using (var dbContext = new OrdersDbContext())
{
var updatedOrder = await dbContext.Orders.Include(c => c.OrderLines)
.Where(c => c.OrderId == order.OrderId).SingleAsync();
//updatedOrder.ShouldNotBeNull();
//customerFetch.Id.ShouldNotBeNull();
//customerFetch.Id.ShouldBe(customerDto.Id);
}
}
}
}
and my order repository update method 和我的订单存储库更新方法
public async Task<Order> UpdateAsync(Order order)
{
var dbOrder = await GetOrderAsync(order.OrderId);
if (dbOrder == null)
throw new Exception($"Invalid Or Missing Order with Id {order.OrderId}");
_dbContext.Update(order);
await _dbContext.SaveChangesAsync();
return order;
}
Note: you can get the code on this github repository code repository 注意:您可以在此github存储库代码存储库中获取代码
When you query the database for some record without using AsNoTracking
EF Core will start tracking it in current context. 在不使用
AsNoTracking
情况下查询数据库某些记录时,EF Core将开始在当前上下文中跟踪它。 So when you update Entity in your code, EF Core finds multiple entities with same id hence the error. 因此,当您在代码中更新实体时,EF Core会找到具有相同ID的多个实体,因此会出现错误。
AsNoTracking
is one solution as you don't want EF Core to track any modifications to that. AsNoTracking
是一种解决方案,因为您不希望EF Core跟踪对此的任何修改。 In many cases not having AsNoTracking
is fine as long as you don't add/attach/update entity with same id in the context. 在许多情况下,只要您不在上下文中添加/附加/更新具有相同ID的实体,就可以不使用
AsNoTracking
。 But it is good to have it explicitly when tracking is not required. 但是,当不需要跟踪时,最好将其明确显示。
Your code has few issues. 您的代码几乎没有问题。 First of all, you cannot new up OrdersDbContext whenever you need it.
首先,您无法在需要时随时更新OrdersDbContext。 If you do so, the instance of the entity cannot be tracked as exception message stated.
如果这样做,则无法按照说明的异常消息来跟踪实体的实例。
For Unit Tests, you need to use either In-Memory Database or mock OrdersDbContext with Mocking Library such as Moq. 对于单元测试,您需要使用内存数据库或带有模拟库(例如Moq)的模拟OrdersDbContext。
If you call async extension methods, then you need to implement async query provider . 如果调用异步扩展方法,则需要实现异步查询提供程序 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.