ASP.Net核心EF的M-M实例无法跟踪

问题描述 投票:2回答:1

请看下面的错误:

InvalidOperationException: The instance of entity type 'OrderRegion' cannot be tracked because another instance with the key value '[Orderid: 10, RegionId: 1]' is already being tracked...

另外,还要考虑以下类(略剪断,为了简洁):

public class Order
…
[Key]
public int Id { get; set; }
…
[Display(Name = "Regions")]
public ICollection<OrderRegion> OrderRegions { get; set; }
[Display(Name = "Stores")]
public ICollection<OrderStore> OrderStores { get; set; }

public class OrderRegion
{
    //[Key]
    public int OrderId { get; set; }
    public Order Order { get; set; }
    //[Key]
    public int RegionId { get; set; }
    public Region Region { get; set; }
}

    public class OrderStore
{
    //[Key]
    public int OrderId { get; set; }
    public Order Order { get; set; }
    //[Key]
    public int StoreId { get; set; }
    public Store Store { get; set; }
}

另外相关的是我创建的关系语境:

public class MyContext:DbContext
{
    public MyContext(DbContextOptions<AzureOrdersContext> options) : base(options) { }

    public DbSet<Order> Order { get; set; }
    public DbSet<OrderRegion> OrderRegion { get; set; }
    public DbSet<OrderStore> OrderStore { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        …
        modelBuilder.Entity<OrderRegion>()
            .HasKey(nr => new { nr.OrderId, nr.RegionId });
        modelBuilder.Entity<OrderRegion>()
            .HasOne(nr => nr.Order)
            .WithMany(n => n.OrderRegions)
            .HasForeignKey(nr => nr.OrderId);
        modelBuilder.Entity<OrderRegion>()
            .HasOne(nr => nr.Region)
            .WithMany(n => n.OrderRegions)
            .HasForeignKey(nr => nr.RegionId);

        modelBuilder.Entity<OrderStore>()
          .HasKey(nr => new { nr.OrderId, nr.StoreId });
        modelBuilder.Entity<OrderStore>()
            .HasOne(nr => nr.Order)
            .WithMany(n => n.OrderStores)
            .HasForeignKey(nr => nr.OrderId);
        modelBuilder.Entity<OrderStore>()
            .HasOne(nr => nr.Store)
            .WithMany(n => n.OrderStores)
            .HasForeignKey(nr => nr.StoreId);
    }
}

最后,我的“Edit.cshtml.cs”在我的错误被抛出(剪断了很多):

public async Task<IActionResult> OnPostAsync(int? id, int[] AssignedRegions, int[] AssignedStores)
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        var Ordertoupdate = await _context.Order
        .Include(i => i.OrderRegions).ThenInclude(navigationPropertyPath: i => i.Region)
        .Include(i => i.OrderStores).ThenInclude(navigationPropertyPath: i => i.Store)
        .FirstOrDefaultAsync(m => m.Id == id);

       ...

        if (await TryUpdateModelAsync<Web.Models.Order>(
                        Ordertoupdate,
                        "Order",
                        i => i.CreatedOn, 
                        i => i.CreatedBy, 
                        i => i.ModifiedBy, i => i.ExpirationDate,
                        ...))
        {
            UpdateOrderRegions(_context, AssignedRegions, Ordertoupdate);
            UpdateOrderStores(_context, AssignedStores, Ordertoupdate);
            await _context.SaveChangesAsync();
            return RedirectToPage("./Index");
        }
        UpdateOrderRegions(_context, AssignedRegions, Ordertoupdate);
        UpdateOrderStores(_context, AssignedStores, Ordertoupdate);
        PopulateAssignedRegions(_context, Ordertoupdate);
        PopulateAssignedStores(_context, Ordertoupdate);
        return Page();
    }

错误是越来越扔在_context.SaveChangesAsync();有任何想法吗?我敢肯定,我只是在做一些愚蠢的事,并没有看到一个简单的解决。

更新包括UpdateOrderRegions的要求:

public void UpdateOrderRegions (AzureOrdersContext _context, int[] SelectedRegions, Web.Models.Order OrderToUpdate)
    {
        if (SelectedRegions == null)
        {
            OrderToUpdate.OrderRegions = new List<OrderRegion>();
            return;
        }
        var StoreRegionsToDelete= OrderToUpdate.OrderRegions.Where<OrderRegion>(nr => {
            return !SelectedRegions.AsQueryable<Int32>().Contains<Int32>(nr.RegionId);
        });

        StoreRegionsToDelete.ToList().ForEach(r => { OrderToUpdate.OrderRegions.Remove(r); });

        var StoreRegionsToAdd = SelectedRegions.AsQueryable<Int32>().Where<Int32>(regionId => 
            !OrderToUpdate.OrderRegions.Any( nr=> nr.RegionId == regionId) 
        );
        StoreRegionsToAdd.ToList().ForEach(regionId => 
        OrderToUpdate.OrderRegions.Add(new OrderRegion
        {
            OrderId = OrderToUpdate.Id,
            RegionId = regionId
        }));

        ////This is where a different, more frustrating logical error lives but isn't related to my EF error
        ////Attempting to model after: https://github.com/aspnet/Docs/blob/master/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/InstructorCoursesPageModel.cshtml.cs

        var selectedRegionHS = new HashSet<string>(SelectedRegions);
        var regionOrders = new HashSet<int>(OrderToUpdate.OrderRegions.Select(c => c.Order.Id)); 
        foreach (var thisregion in _context.Region) 
        {
            if (selectedRegionHS.Contains(thisregion.Id.ToString())) 
            {
               if (!regionOrders.Contains(thisregion.Id)) 
                {
                    OrderToUpdate.OrderRegions.Add( 
                       new OrderRegion
                        {
                            OrderId = OrderToUpdate.Id,
                            RegionId = thisregion.Id
                        });
                }
            }

           else
           {
                if (regionOrders.Contains(thisregion.Id))
                {
                    OrderRegion RegionToRemove = OrderToUpdate.OrderRegions.SingleOrDefault(i => i.RegionId == thisregion.Id);
                    _context.Remove(RegionToRemove);
                }
            }
        }
    }
entity-framework asp.net-core
1个回答
2
投票

当上下文已经有一个项目跟踪和你明确地尝试连接一个新的对象具有相同的键出现此问题。

考虑到误差是OrderRegion这种类型具有的OrderId / RegionId的复合键,我认为这是可能的,你是检索OrderRegion并连接使用相同的OrderId / RegionId组合新OrderRegion。您可能需要检查是否有OrderRegion键已经存在或清除订单的地区,重建列表来避免这种冲突。

我希望这点你在正确的方向。随意提供,你处理OrderRegion更新的代码,我会尽力提供进一步协助。

© www.soinside.com 2019 - 2024. All rights reserved.