【发布时间】:2021-05-08 13:34:02
【问题描述】:
使用 EF Core,我有一个Zone,可以有多个Sol(土壤),相同的Sol 可以附加到多个Zone:
public class Sol
{
// ...
public ICollection<Zone> Zones { get; set; } = new List<Zone>();
}
public class Zone
{
// ...
public ICollection<Sol> Sols { get; set; } = new List<Sol>();
}
public override void Configure(EntityTypeBuilder<Zone> builder)
{
// ...
builder
.HasMany(p => p.Sols)
.WithMany(p => p.Zones);
}
将我的 Sols 添加到区域时,我得到以下异常:
Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。
Microsoft.Data.SqlClient.SqlException (0x80131904):违反主键约束“PK_SolZone”。无法在对象“dbo.SolZone”中插入重复键。重复键值为 (1, 2)。
一些实现细节:
在我的控制器中,当我检索对象时
public override async Task<IActionResult> Edit(int id, [FromQuery] bool fullView)
{
var currentZone = _repository.SingleOrDefault(new GetZoneWithPaysAndSolsSpecification(id));
在哪里
public class GetZoneWithPaysAndSolsSpecification : Specification<Zone>
{
public GetZoneWithPaysAndSolsSpecification(int zoneId)
{
Query.Where(p => p.Id == zoneId);
Query.Include(p => p.Pays);
Query.Include(p => p.Sols);
}
}
在更新对象之前,我将我的 ZoneDTO 转换为 Zone,然后将其添加到数据库中:
protected override void BeforeUpdate(Zone zone, ZoneDTO sourceDto)
{
zone.Sols.Clear();
foreach (var solId in sourceDto.SolIds)
{
var sol = _repository.GetById<Sol>(solId);
zone.Sols.Add(sol);
}
base.BeforeUpdate(zone, sourceDto);
}
我使用基本控制器,它使用BeforeUpdate,就像这样
[HttpPost]
[ValidateAntiForgeryToken]
public virtual async Task<IActionResult> Edit(TDto dto)
{
try
{
var entity = FromDto(dto);
BeforeUpdate(entity, dto);
await _repository.UpdateAsync(entity);
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
_logger.LogError(ex, "when editing an object after submit");
return PartialView();
}
}
存储库代码
public Task UpdateAsync<T>(T entity) where T : BaseEntity
{
_dbContext.Entry(entity).State = EntityState.Modified;
return _dbContext.SaveChangesAsync();
}
我使用 AutoMapper
protected TBussinesModel FromDto(TDto dto)
{
return _mapper.Map<TBussinesModel>(dto);
}
而且映射是这样的
CreateMap<Zone, ZoneDTO>()
.ForMember(p => p.SolIds, o => o.MapFrom(p => p.Sols.Select(s => s.Id).ToArray()))
.ForMember(p => p.SolNoms, o => o.MapFrom(p => p.Sols.Select(s => s.Nom).ToArray()))
.ReverseMap();
【问题讨论】:
-
从错误消息中,您在数据库中插入了重复键。
-
@Karney。我明白了,谢谢。我在 OP 中添加了更多细节,以便更好地阐明上下文
-
@Serge 你能分享
FromDto方法的代码吗? -
@atiyar 我添加了代码,不确定它是否与问题相关,无论如何它会很棒
标签: c# .net entity-framework-core ef-core-5.0