简体   繁体   English

当我尝试使用带有AutoMapper的Entity Framework Core更新图时出现异常

[英]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.

相关问题 在实体框架中使用AutoMapper的异常 - Exception using AutoMapper with Entity Framework 使用 AutoMapper 时添加 EF Core 实体而不是更新 - EF Core entity is added instead of update when using AutoMapper 如何使用自动映射器更新实体框架中的数据? - How to update data in entity framework using automapper? 我正在尝试使用 Entity Framework Core 更新表中的记录,但出现异常 - I am trying to update a record in a table using Entity Framework Core but I am getting an exception 映射包含导航属性的实体框架实体时,Automapper异常 - Automapper Exception when mapping Entity Framework entity that contains a navigation property 当我尝试更新实体时,EF6引发EntityValidationErrors异常 - EF6 Throws Exception for EntityValidationErrors When I Try to Update Entity 如何在 Entity Framework Core 中使用 Automapper 删除可选关系 - How can I remove an optional relationship using Automapper in Entity Framework Core 自动映射器,实体框架更新数据库 - Automapper, Entity framework update database 使用 AutoMapper 无法 Map 复杂实体框架核心 - Unable to Map Complex Entity Framework Core using AutoMapper 当我尝试更新父实体时,实体框架正在更新子实体 - Entity Framework is updating child entity when I try to update parent entity
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM