Asp.net core System.InvalidOperationException:无法跟踪实体类型x的实例

Posted

技术标签:

【中文标题】Asp.net core System.InvalidOperationException:无法跟踪实体类型x的实例【英文标题】:Asp.net core System.InvalidOperationException: The instance of entity type x cannot be tracked 【发布时间】:2021-05-04 01:11:52 【问题描述】:

我是 asp.net core 的新手,我从 udemy 获得了一门课程。我做的一切都像教练一样。当我尝试将测试数据添加到数据库时,出现System.InvalidOperationException: 'The instance of entity type 'ProductCategory' cannot be tracked because another instance with the same key value for 'CategoryId', 'ProductId' is already being tracked. 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.' 错误。 我对此进行了很多研究,但我一无所知,因为这对我来说似乎很复杂。

SeedDatabase.cs

using Entity.Models;
using Microsoft.EntityFrameworkCore;
using ShopApp.Entity.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Data.Concrete.EfCore

    public static class SeedDatabase
    
        public static void seed()
        
            var context = new ShopContext();

            if (context.Database.GetPendingMigrations().Count() == 0)
            
                if (context.Categories.Count() == 0)
                
                    context.Categories.AddRange(categories);
                

                if (context.Products.Count() == 0)
                
                    context.Products.AddRange(Products);
                    context.AddRange(ProductCategories);
                
            
            context.SaveChanges();
        
        private static Category[] categories = 
            new Category()Name="Kağıt",
            new Category()Name="Kalem",
            new Category()Name="Sarf Malzemesi"
        ;

        private static Product[] Products = 
            new Product()Name="A4 Kağıt",price=11.5,quantity=12,CategoryId=0,
            new Product()Name="Faber Kalem",price=7,quantity=54,CategoryId=1,
            new Product()Name="Yazıcı Çarkı",price=3,quantity=87,CategoryId=2,
            new Product()Name="Dosya Kağıdı",price=0.10,quantity=850,CategoryId=0,
            new Product()Name="Rotring Kalem",price=16,quantity=125,CategoryId=1,
            new Product()Name="Toner",price=65,quantity=14,CategoryId=2
        ;
        private static ProductCategory[] ProductCategories = 
            new ProductCategory()Product=Products[0],Category=categories[0],
            new ProductCategory()Product=Products[0],Category=categories[1],
            new ProductCategory()Product=Products[1],Category=categories[0],
            new ProductCategory()Product=Products[0],Category=categories[1]
        ;
    

产品.cs

namespace ShopApp.Entity.Models

    public class Product
    

        public int Id  get; set; 
        [Required(ErrorMessage ="Lütfen isim giriniz")]
        public string Name  get; set; 
        [Required(ErrorMessage = "Lütfen fiyat giriniz")]
        public double? price  get; set; 
        [Required(ErrorMessage = "Lütfen adet giriniz")]
        public double? quantity  get; set; 
        public string ImageUrl  get; set; 
        [Required(ErrorMessage = "Lütfen kategori seçiniz")]
        public int? CategoryId  get; set; 
        //public Category Category  get; set; 
        public List<ProductCategory> ProductCategories  get; set; 
    

Category.cs

namespace ShopApp.Entity.Models

    public class Category
            
        public int id  get; set; 
        public string Name  get; set; 
        public string Description  get; set; 
        public List<ProductCategory> ProductCategories  get; set; 
    

ProductCategory.cs

namespace Entity.Models

    public class ProductCategory
    
        public int CategoryId  get; set; 
        public Category Category  get; set; 
        public int ProductId  get; set; 
        public Product Product  get; set; 
    

ShopContext.cs

namespace Data.Concrete.EfCore

    public class ShopContext:DbContext
    
        public DbSet<Product> Products  get; set; 
        public DbSet<Category> Categories  get; set; 
    

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        
            optionsBuilder.UseSqlite("DataSource=ShopDb");
        
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        
            modelBuilder.Entity<ProductCategory>().HasKey(c => new  c.CategoryId, c.ProductId );
         
    

我尝试创建具有多对多关系的表,这意味着一个产品可能属于多个类别,一个类别可能属于多个产品。

【问题讨论】:

最后一个 new ProductCategory()Product=Products[0],Category=categories[1],在数组中出现了两次。应该是 new ProductCategory()Product=Products[1],Category=categories[1] 吗? @JMP 不,这意味着多对多关系 我认为是因为您的复合键,在 productcategory 上使用 haskey 时,它会检索 2 个 CategoryId 和 2 个 ProductId 【参考方案1】:

当我们按照它的工作方式更改代码时,它会抛出错误,因为在添加类别和产品之后,我必须运行 savechanges(),因为产品和类别必须从数据库中获取 id,然后我们才能标记产品类别。

SeedDatabase.cs

namespace Data.Concrete.EfCore

    public static class SeedDatabase
    
        public static void seed()
        

            var context = new ShopContext();

            if (context.Database.GetPendingMigrations().Count() == 0)
            

                if (context.Categories.Count() == 0 && context.Products.Count() == 0)
                
                    var cats = new List<Category> 
                        new Category()Name="Kağıt",
                        new Category()Name="Kalem",
                        new Category()Name="Sarf Malzemesi"
                    ;
                    context.Categories.AddRange(cats);



                    context.SaveChanges();
                    var prods = new List<Product>
                        new Product()  Name = "A4 Kağıt", price = 11.5, quantity = 12, CategoryId = cats[0].id ,
                        new Product()  Name = "Faber Kalem", price = 7, quantity = 54, CategoryId = cats[1].id ,
                        new Product()  Name = "Yazıcı Çarkı", price = 3, quantity = 87, CategoryId = cats[2].id ,
                        new Product()  Name = "Dosya Kağıdı", price = 0.10, quantity = 850, CategoryId =cats[0].id ,
                        new Product()  Name = "Rotring Kalem", price = 16, quantity = 125, CategoryId =cats[1].id ,
                        new Product()  Name = "Toner", price = 65, quantity = 14, CategoryId = cats[2].id 
                    ;
                    context.Products.AddRange(prods);
                    context.SaveChanges();
                    var prodVats = new List<ProductCategory>();
                    for (int i = 0; i < prods.Count; i++)
                    
                        prodVats.Add(new ProductCategory  CategoryId = prods[i].CategoryId.Value, ProductId = prods[i].Id );
                    
                    context.AddRange(prodVats);
                    context.SaveChanges();


                

            
        
    
    


【讨论】:

以上是关于Asp.net core System.InvalidOperationException:无法跟踪实体类型x的实例的主要内容,如果未能解决你的问题,请参考以下文章

Asp.NET Core进阶 第四篇 Asp.Net Core Blazor框架

.NET Core 1.0ASP.NET Core 1.0和EF Core 1.0简介

asp.net core 注入后仍然报错?

深入研究 Mini ASP.NET Core(迷你 ASP.NET Core),看看 ASP.NET Core 内部到底是如何运行的

.Net Core 学习 - ASP.NET Core 概念学习

ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 14. ASP.NET Core Identity 入门