gpt4 book ai didi

c# - Entity Framework Core 在更新期间删除实体

转载 作者:行者123 更新时间:2023-12-05 07:07:15 25 4
gpt4 key购买 nike

我对 ASP.NET Core 中的实体有疑问。我使用 Entity Framework 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);
}

有人知道如何解决这个问题吗?

更新:

这是新的更新方法:

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 方法中调用。

最佳答案

我终于设法解决了我的问题。我已经在我的 api Controller 中跟踪实体了:

[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 无法正确跟踪更改。如果有人遇到我同样的问题,我会发布我的新 Controller 和存储库代码。 Controller :

[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);
}

我要感谢大家,你们对我非常有帮助和耐心。

关于c# - Entity Framework Core 在更新期间删除实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62238065/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com