无法跟踪实体类型“ Customer”的实例,因为已经跟踪了另一个键值为“ {Id:...}”的实例

时间:2019-08-23 20:50:15

标签: c# asp.net-mvc entity-framework-core

我已经在寻找类似的问题,但是它们并没有太大帮助。在我看来,我的DbContext需要进行范围调整以防止这种情况。即使我以前实现了“ AddScoped”,它仍然无法正常工作。

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
    {
        options.EnableSensitiveDataLogging();
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));

    }, ServiceLifetime.Scoped);

    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
         AddEntityFrameworkStores<ApplicationDbContext>();

    services.Configure<IdentityOptions>(options =>
    {
     ...
    });    
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    services.AddScoped<ISmartyService, SmartyService>();
}

DbContext:

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
{
}

public DbSet<Brand> Brand { get; set; }
public DbSet<Car> Car { get; set; }
public DbSet<Customer> Customer { get; set; }
public DbSet<Expense> Expense { get; set; }
public DbSet<Expensetype> Expensetype { get; set; }

表格

汽车

public Guid Id { get; set; }

[ForeignKey("Customer")]
public Guid? Customer_Id { get; set; }

[ForeignKey("Brand")]
public Guid Brand_Id { get; set; }

public string Name { get; set; }

public int Purchase_Price { get; set; }

public int Selling_Price { get; set; }

public int Mileage { get; set; }        

public DateTime InCirculationSince { get; set; }

public DateTime Purchased_At { get; set; }

public DateTime Sold_At { get; set; }

public byte[] Picture { get; set; }

public Customer Customer { get; set; }

public Brand Brand { get; set; }

客户

public Guid Id { get; set; }

[Required]
public string Firstname { get; set; }

[Required]
public string Lastname { get; set; }

public string Address { get; set; }

[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }

[DataType(DataType.PhoneNumber)]
public string Telephone { get; set; }

品牌

public Guid Id { get; set; }

public string Brandname { get; set; }

其他表不是必需的atm。我没有机会研究它们。我真的不能说我在做什么错。我认为我为上传实现的逻辑是正确的。可能这就是我做错的部分。对于上传,我正在使用以下代码:

public void AddOrUpdateCar(Car car)
{
    if (car.Id == Guid.Empty)
    {
        dbContext.Car.Add(car);
    }
    else
    {
        //Where the error occurs
        dbContext.Car.Update(car);
    }

    dbContext.SaveChanges();
}

在控制器中:

        Car car = null;

        //Update Condition
        if (viewModel.Id != Guid.Empty)
        {
            car = service.GetCar(viewModel.Id);

            car.Name = service.GetBrandAsString(viewModel.Brand) + " " + viewModel.Name;
            car.Brand_Id = viewModel.Brand;
            car.Purchase_Price = viewModel.Purchase_Price;
            car.Mileage = viewModel.Mileage;
            car.InCirculationSince = viewModel.InCirculationSince;
            car.Purchased_At = viewModel.Purchased_At;

            if (viewModel.Customer != null)
            {
                car.Customer_Id = viewModel.Customer.Id;

                //Applying changes to customer
                car.Customer.Firstname = viewModel.Customer.Firstname;
                car.Customer.Lastname = viewModel.Customer.Lastname;
                car.Customer.Address = viewModel.Customer.Address;
                car.Customer.Email = viewModel.Customer.Email;
                car.Customer.Telephone = viewModel.Customer.Telephone;
            }
        }
        //Add condition
        else
        {
            car = new Car()
            {
                Name = service.GetBrandAsString(viewModel.Brand) + " " + viewModel.Name,
                Brand_Id = viewModel.Brand,
                Purchase_Price = viewModel.Purchase_Price,
                Mileage = viewModel.Mileage,
                InCirculationSince = viewModel.InCirculationSince,
                Purchased_At = viewModel.Purchased_At                  
            };
        }

        if (viewModel.Picture != null)
        {
            car.Picture = ResizeImage(viewModel.Picture, 285, 144);
        }

        service.AddOrUpdateCar(car);

完整的错误消息

System.InvalidOperationException: 'The instance of entity type 'Customer' cannot be tracked because another instance with the key value '{Id: 626c03d3-4d66-44db-acad-1342dd9bc4ae}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.'

任何帮助将不胜感激!任何有助于减轻此问题困扰的帮助

2 个答案:

答案 0 :(得分:0)

在您的控制器代码中,您正在创建Car实体的新实例以对其进行更新(我假设...是因为您使用viewModel.Id作为ID)。 / p>

因为您正在创建此实例,而不是从上下文中检索它,所以上下文不会对其进行跟踪,并且在尝试更新时会收到此错误,因为新创建的{{ 1}}实例与上下文已经跟踪的实例匹配。

为了更新现有实体,您需要首先从上下文中检索它,然后根据需要更改其属性,然后Id对其进行编辑...

Car

答案 1 :(得分:0)

经过大量的尝试,我终于能够解决问题。即使我以前是这样更新客户的:

car.Customer = viewModel.Customer;

它没有应用更改。我相信EF Core认为一切都没有改变,并且我正在尝试添加具有相同ID的新项目。因此,在告知EF Core客户已通过应用更改进行了更改之后,它可以正常工作。

我更改了问题代码以解释我的答案。我不得不更改控制器中的代码。