实体框架核心在更新期间删除实体

时间:2020-06-06 21:09:50

标签: c# entity-framework-core

我在ASP.NET Core中遇到有关实体的问题。 我使用实体框架核心作为数据访问库。 我遇到的问题是在尝试更新实体时发生的。修改属性并调用SaveChanges之后,该实体将被删除,并且我不明白为什么。 这是实体:

public class Contract
    {
        public int Id { get; set; }
        [Required]
        public DateTime ExpiryDate { get; set; }
        [Required]
        [Range(0, float.MaxValue)]
        public float MonthlyFee { get; set; }
        [Required]
        public string UserId { get; set; }
        [Required]
        public int CarId { get; set; }
        public User User { get; set; }
        public Car Car { get; set; }
    }

以下是相关实体供参考:

public class User : IdentityUser
    {
        [Required]
        [PersonalData]
        public string Name { get; set; }
        [Required]
        [PersonalData]
        public string Surname { get; set; }
        [Required]
        [PersonalData]
        public string TaxCode { get; set; }
        [Required]
        [PersonalData]
        [DataType(DataType.Date)]
        public DateTime DateOfBirth { get; set; }
        public string ProfilePictureUrl { get; set; }
        
        public Contract Contract { get; set; }

        public ICollection<CarAccident> CarAccidents { get; set; }
    }
public class Car
    {
        public int Id { get; set; }
        [Required]
        [RegularExpression("[A-Z][A-Z][0-9][0-9][0-9][A-Z][A-Z]")]
        public string LicensePlate { get; set; }
        public int CarModelId { get; set; }
        public string FittingDescription { get; set; }
        public Contract Contract { get; set; }

        public ICollection<CarAccident> CarAccidents { get; set; }

        public CarModel CarModel { get; set; }
    }

这是我在存储库中的更新方法:

public async Task<Contract> Update(Contract entity)
        {
            var dbContract = await GetById(entity.Id);
            if (dbContract == null)
                return null;

            var dbUser = await _userRepository.GetById(entity.UserId);
            if (dbUser == null)
                return null;

            var dbCar = await _carRepository.GetById(entity.CarId);
            if (dbCar == null)
                return null;

            dbContract.ExpiryDate = entity.ExpiryDate;
            dbContract.User = entity.User;
            dbContract.Car = dbCar;
            dbContract.User = dbUser;

            //_context.Contracts.FromSqlInterpolated($"UPDATE dbo.Contracts SET ExpiryDate={entity.ExpiryDate}, MonthlyFee={entity.MonthlyFee} WHERE Id={entity.Id}");

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                return null;
            }

            return await GetById(entity.Id);
        }

有人知道如何解决吗?

更新:

这是新的Update方法:

public async Task<Contract> Update(Contract entity)
        {
            var dbContract = await GetById(entity.Id);
            if (dbContract == null)
                return null;

            var dbUser = await _userRepository.GetById(entity.UserId);
            if (dbUser == null)
                return null;

            var dbCar = await _carRepository.GetById(entity.CarId);
            if (dbCar == null)
                return null;

            dbContract.ExpiryDate = entity.ExpiryDate;
            dbContract.Car = dbCar;
            dbContract.User = dbUser;

            //_context.Contracts.FromSqlInterpolated($"UPDATE dbo.Contracts SET ExpiryDate={entity.ExpiryDate}, MonthlyFee={entity.MonthlyFee} WHERE Id={entity.Id}");

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                return null;
            }

            return await GetById(entity.Id);
        }

这是Fluent API配置:

private void _configureUsers(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>()
                .HasOne(u => u.Contract)
                .WithOne(c => c.User)
                .HasForeignKey<Contract>(c => c.UserId);
        }
private void _configureCars(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Car>()
                .HasAlternateKey(c => c.LicensePlate);

            modelBuilder.Entity<Car>()
                .HasOne(c => c.Contract)
                .WithOne(c => c.Car)
                .HasForeignKey<Contract>(c => c.CarId);
        }

这两个方法都在上下文的OnModelCreating方法中调用。

1 个答案:

答案 0 :(得分:0)

我终于设法解决了我的问题。 我已经在api控制器中像这样跟踪实体:

[HttpPut("{id}")]
        [Authorize(Roles = "Backoffice")]
        public async Task<ActionResult<ContractDTO>> PutContract(int id, [FromBody] PutContractViewModel viewModel)
        {
            if (viewModel == null || !ModelState.IsValid)
                return BadRequest(new { message = "Your model is wrong" });


            var contract = await _contractService.GetContractDTO(id);

            if (contract == null)
                return NotFound();

            var modifiedContract = await _contractService.UpdateContract(viewModel);

            if (modifiedContract == null)
                return BadRequest(new { message = "User or car may be busy in another contract" });

            return Ok(modifiedContract);
        }

这种方法在一对多关系中起作用,但是很明显,当您具有一对一关系并且必须呈现相同实体的对象时,ChangeTracker无法正确跟踪更改。 如果有人遇到同样的问题,我会发布新的控制器和存储库代码。 控制器:

[HttpPut("{id}")]
        [Authorize(Roles = "Backoffice")]
        public async Task<ActionResult<ContractDTO>> PutContract(int id, [FromBody] PutContractViewModel viewModel)
        {
            if (viewModel == null || !ModelState.IsValid)
                return BadRequest(new { message = "Your model is wrong" });


            ContractDTO modifiedContract;
            try
            {
                modifiedContract = await _contractService.UpdateContract(viewModel);
            }
            catch (EntityNotFoundException)
            {
                return NotFound();
            }


            if (modifiedContract == null)
                return BadRequest(new { message = "User or car may be busy in another contract" });

            return Ok(modifiedContract);

服务:

public async Task<ContractDTO> UpdateContract(PutContractViewModel viewModel)
        {
            try
            {
                return await ParseContractToContractDTO(await _contractRepository.Update(ParsePutContractViewModelToContract(viewModel)));
            }
            catch(EntityNotFoundException)
            {
                throw;
            }
        }

存储库:

public async Task<Contract> Update(Contract entity)
        {

            var dbContract = await _context.Contracts.Include(c => c.User).Include(c => c.Car).FirstOrDefaultAsync(c => c.Id == entity.Id);

            if (dbContract == null)
            {
                throw new EntityNotFoundException();
            }

            var dbUser = await _context.Users.Include(u => u.Contract).FirstOrDefaultAsync(u => u.Id == entity.UserId);

            if (dbUser == null)
                return null;

            var dbCar = await _context.Cars.Include(c => c.Contract).FirstOrDefaultAsync(c => c.Id == entity.CarId);

            if (dbCar == null)
                return null;


            dbContract.ExpiryDate = entity.ExpiryDate;
            dbContract.MonthlyFee = entity.MonthlyFee;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                return null;
            }



            return await GetById(entity.Id);
        }

我要感谢大家,您对我很有帮助,并且对我耐心。