I've already been looking for similar questions but they didn't help me much. It seems to me that my DbContext needs to be Scoped in order to prevent this. Even though I implemented 'AddScoped' previously, it still did not work.
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; }
Tables
Car
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; }
Customer
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; }
Brand
public Guid Id { get; set; }
public string Brandname { get; set; }
The other tables are not necessary atm. I didn't have the chance to work on them. I can't really tell what I'm doing wrong. I believe that the logic I implemented for the upload is correct. It could be that this it the part that I'm doing wrong. for the Upload I'm using the following code:
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();
}
In Controller:
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);
Full error message
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.'
Any help will be appreciated! Any help that makes this problem less excruciating
After a lot of trying, I was finally able to solve the problem. Even though I previously updated the customer like this:
car.Customer = viewModel.Customer;
It didn't apply the changes. I believe that EF Core thought that nothing has changed and that I'm trying to add a new item with the same Id. So after telling EF Core that the customer has changed by applying the changes, it worked perfectly.
I changed the code in my question in order to explain my answer. I had to change the code in the controller.