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

C# 实体框架核心在更新期间删除实体,c#,entity-framework-core,C#,Entity Framework Core,我有一个关于ASP.NET核心中实体的问题。 我使用实体框架核心作为数据访问库。 我遇到的问题发生在我尝试更新实体时。在我修改属性并调用SaveChanges之后,实体被删除,我不明白为什么。 以下是实体: public class Contract { public int Id { get; set; } [Required] public DateTime ExpiryDate { get; set; } [Requi

我有一个关于ASP.NET核心中实体的问题。 我使用实体框架核心作为数据访问库。 我遇到的问题发生在我尝试更新实体时。在我修改属性并调用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; }
    }
公共类用户:IdentityUser
{
[必需]
[个人资料]
公共字符串名称{get;set;}
[必需]
[个人资料]
公共字符串姓氏{get;set;}
[必需]
[个人资料]
公共字符串TaxCode{get;set;}
[必需]
[个人资料]
[数据类型(DataType.Date)]
公共日期时间出生日期{get;set;}
公共字符串ProfilePictureUrl{get;set;}
公共合同{get;set;}
公共ICollection CarAccidents{get;set;}
}
公车
{
公共int Id{get;set;}
[必需]
[常规表达(“[A-Z][A-Z][0-9][0-9][0-9][A-Z][A-Z]”)
公共字符串许可证牌{get;set;}
公共int CarModelId{get;set;}
公共字符串FittingDescription{get;set;}
公共合同{get;set;}
公共ICollection CarAccidents{get;set;}
公共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);
        }
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);
        }
公共异步任务更新(合同实体)
{
var dbContract=await GetById(entity.Id);
if(dbContract==null)
返回null;
var dbUser=await_userRepository.GetById(entity.UserId);
if(dbUser==null)
返回null;
var dbCar=await_carRepository.GetById(entity.CarId);
if(dbCar==null)
返回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},其中Id={entity.Id}”);
尝试
{
wait_context.SaveChangesAsync();
}
捕获(DbUpdateException)
{
返回null;
}
返回等待GetById(entity.Id);
}
有人知道怎么解决这个问题吗

更新: 这是新的更新方法:

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);
        }
公共异步任务更新(合同实体)
{
var dbContract=await GetById(entity.Id);
if(dbContract==null)
返回null;
var dbUser=await_userRepository.GetById(entity.UserId);
if(dbUser==null)
返回null;
var dbCar=await_carRepository.GetById(entity.CarId);
if(dbCar==null)
返回null;
dbContract.ExpiryDate=entity.ExpiryDate;
dbContract.Car=dbCar;
dbContract.User=dbUser;
//_context.Contracts.FromSqlInterpolated($“UPDATE dbo.Contracts SET ExpiryDate={entity.ExpiryDate},MonthlyFee={entity.MonthlyFee},其中Id={entity.Id}”);
尝试
{
wait_context.SaveChangesAsync();
}
捕获(DbUpdateException)
{
返回null;
}
返回等待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);
        }
private void\u配置用户(ModelBuilder ModelBuilder)
{
modelBuilder.Entity()
.HasOne(u=>u.Contract)
.WithOne(c=>c.User)
.HasForeignKey(c=>c.UserId);
}
专用void\u配置车辆(ModelBuilder ModelBuilder)
{
modelBuilder.Entity()
.HasaAlternateKey(c=>c.LicensePlate);
modelBuilder.Entity()
.HasOne(c=>c.Contract)
.带一个(c=>c.Car)
.HasForeignKey(c=>c.CarId);
}

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

我终于设法解决了我的问题。 我已经在跟踪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);
        }
[HttpPut(“{id}”)]
[授权(角色=“后台”)]
公共异步任务PutContract(int id,[FromBody]PutContractViewModel viewModel)
{
if(viewModel==null | |!ModelState.IsValid)
返回BadRequest(新建{message=“您的模型错误”});
var contract=await\u contractService.GetContractDTO(id);
如果(合同==null)
返回NotFound();
var modifiedContract=await _contractService.UpdateContract(viewModel);
if(modifiedContract==null)
return BadRequest(新建{message=“用户或车辆可能在另一个合同中忙碌”});
返回Ok(修改后的合同);
}
这种类型的方法适用于一对多关系,但显然,当您有一对一关系,并且必须创建表示同一实体的对象时,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);
[HttpPut(“{id}”)]
[授权(角色=“后台”)]
公共异步任务PutContract(int id,[FromBody]PutContractViewModel viewModel)
{
if(viewModel==null | |!ModelState.IsValid)
返回BadRequest(新建{message=“您的模型错误”});
修改合同的合同;
尝试
{
modifiedContract=Wait_contractService.UpdateContact(viewModel);
}
捕获(EntityNotFoundException)
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);
        }