首页 > 解决方案 > 无法跟踪实例,因为已跟踪具有相同键的另一个实例

问题描述

我刚开始使用 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 这样的子实例。

标签: c#entity-frameworkasp.net-core

解决方案


我通过创建 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);
        }

推荐阅读