c# - 无法跟踪实例,因为已跟踪具有相同键的另一个实例
问题描述
我刚开始使用 asp.net core MVC 开发汽车租赁应用程序,我正在使用 EF Core 处理数据库。当我尝试从数据库更新记录时,问题就来了。它给了我以下例外:
InvalidOperationException:无法跟踪实体类型“Car”的实例,因为已经在跟踪具有相同键值 {'CarID'} 的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用“DbContextOptionsBuilder.EnableSensitiveDataLogging”来查看冲突的键值。
这是我更新汽车的代码:
存储库:
public Car GetCarByID(int carId)
{
return _context.Cars.Where(c=> c.CarID == carId).Include(c=>c.Category)
.Include(c=>c.Type)
.Include(c=>c.CarLocations).ThenInclude(c=>c.Location)
.FirstOrDefault();
}
public void UpdateCar(Car car)
{
_context.Update(car);
}
控制器车更新代码:
[HttpGet]
public async Task<IActionResult> Edit(int id)
{
await SeedCarView();
var carToEdit = _carsRepo.GetCarByID(id);
if (carToEdit == null)
{
return NotFound();
}
return View(carToEdit);
}
[HttpPost]
public async Task<IActionResult> Edit(Car car)
{
await SeedCarView();
if (ModelState.IsValid)
{
/*get selections from dropdown form*/
string categSelection = Request.Form["Category_Name"].ToString();
string bodySelection = Request.Form["TypeName"].ToString();
var selectedLocations = Request.Form["AreChecked"].ToList();
var selectedCategory = await _categoriesRepo.GetCategoryByIDAsync(categSelection);
var selectedBodyType = await _typesRepo.GetBodyTypeByNameAsync(bodySelection);
car.Category = selectedCategory;
/*Increment the number of cars in this category*/
car.Category.NumberOfCars = car.Category.Cars.Count + 1;
car.Type = selectedBodyType;
foreach (var sel in selectedLocations)
{
CarLocation carLocation = new CarLocation
{
Car = car
};
var location = _locationsRepo.GetLocationByID(Int32.Parse(sel));
carLocation.Location = location;
car.CarLocations.Add(carLocation);
}
_carsRepo.UpdateCar(car);
await _carsRepo.SaveAsync();
return RedirectToAction("Listing");
}
return View(car);
}
private async Task SeedCarView()
{
var categories = await _categoriesRepo.GetCategoriesAsync();
var bodyTypes = await _typesRepo.GetBodyTypesAsync();
var locations = await _locationsRepo.GetLocationsAsync();
List<string> categorieNames = new List<string>();
List<string> typeNames = new List<string>();
/*get the existing categories name and body types name*/
foreach (var item in categories)
categorieNames.Add(item.Category_Name);
foreach (var item in bodyTypes)
typeNames.Add(item.Name);
ViewBag.Category_Names = categorieNames;
ViewBag.TypeNames = typeNames;
ViewBag.LocationNames = locations;
}
这是服务配置方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<CarRentalContext>(item => item.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<ICarsRepository, CarsRepository>();
services.AddScoped<ICarCategoryRepository, CarCategoryRepository>();
services.AddScoped<ICarTypeRepository, CarTypeRepository>();
services.AddScoped<ILocationsRepository, LocationsRepository>();
}
请帮我解决这个问题。我被困在这个问题上超过 2 天,我不明白问题出在哪里。
更新:
我已经使用以下代码更改了存储库中的更新方法:
public void UpdateCar(Car car)
{
var existingCar = GetCarByID(car.CarID);
_context.Entry(existingCar).CurrentValues.SetValues(car);
//_context.Update(car);
}
以及 POST 操作中的代码:
foreach (var sel in selectedLocations)
{
var location = _locationsRepo.GetLocationByID(Int32.Parse(sel));
CarLocation carLocation = new CarLocation
{
CarID = car.CarID,
LocationID = location.Location_ID,
Car = car,
Location = location
};
car.CarLocations.Add(carLocation);
}
但现在只有汽车实例被更新,没有像 CarCategory、Locations 和 CarType 这样的子实例。
解决方案
我通过创建 Car 的新实例、清理其旧数据并添加更改的属性来解决异常。
public async Task<IActionResult> Edit(Car car)
{
await SeedCarView();
if (ModelState.IsValid)
{
/*get selections from dropdown form*/
string categSelection = Request.Form["Category_Name"].ToString();
string bodySelection = Request.Form["TypeName"].ToString();
var selectedLocations = Request.Form["AreChecked"].ToList();
var selectedCategory = await _categoriesRepo.GetCategoryByIDAsync(categSelection);
var selectedBodyType = await _typesRepo.GetBodyTypeByNameAsync(bodySelection);
var carToBeUpdated = _carsRepo.GetCarByID(car.CarID);
carToBeUpdated.CarLocations.Clear();
foreach (var sel in selectedLocations)
{
var location = _locationsRepo.GetLocationByID(Int32.Parse(sel));
CarLocation carLocation = new CarLocation
{
CarID= car.CarID,
LocationID = location.Location_ID,
Car = car,
Location = location
};
carToBeUpdated.CarLocations.Add(carLocation);
}
carToBeUpdated.Category = selectedCategory;
carToBeUpdated.CategoryName = categSelection;
/*Increment the number of cars in this category*/
carToBeUpdated.Category.NumberOfCars = carToBeUpdated.Category.Cars.Count + 1;
carToBeUpdated.Type = selectedBodyType;
carToBeUpdated.TypeID = selectedBodyType.TypeID;
carToBeUpdated.Acceleration = car.Acceleration;
carToBeUpdated.ClimateControll = car.ClimateControll;
carToBeUpdated.Fabrication_Date = car.Fabrication_Date;
carToBeUpdated.FuelType = car.FuelType;
carToBeUpdated.Model = car.Model;
carToBeUpdated.PictureURL = car.PictureURL;
carToBeUpdated.TransmisionType = car.TransmisionType;
carToBeUpdated.PricePerDay = car.PricePerDay;
//_carsRepo.UpdateCar(carToBeUpdated);
await _carsRepo.SaveAsync();
return RedirectToAction("Listing");
}
return View(car);
}
推荐阅读
- firebase - Firebase 消息传递的 Firebase Flutter 升级问题
- postgresql - 使用 Golang 从 PostgreSQL 数据库中检索数据的问题
- ping - Windows 10 Ping 脚本和颜色输出
- javascript - 如何在反应路由器 dom 中使用 onEnter 和 onLeave 函数?
- ios - 未显示特性 - iOS 是否有 BLE 外围特性规范
- r - 鉴于强制引入的 NA,Sweave/R/Latex 中没有 pdflatex
- reactjs - 在堆栈中的堆栈导航器之间重置并传递参数
- php - 如何从矩形中获取信息并将其发送到 html 中的电子邮件
- javascript - NextJS 映射数组从 Formik 到 Router.Push
- reactjs - 使用 checkCrossOrigin={false} 时如何修复 React-cropper 的错误?