我很难弄清楚如何更新集合。
这是我的模特
public class ProgramacionSemanal
{
public int ProgramacionSemanalId { get; set; }
public int Semana { get; set; }
public DateTime FechaInicio { get; set; }
public DateTime FechaFin { get; set; }
public ICollection<ProgramacionSemanalDetalle> ProgramacionSemanalDetalles { get; set; }
}
public class ProgramacionSemanalDetalle
{
[Key]
public int ProgramacionSemanalDetalleId { get; set; }
public int ProgramacionSemanalId { get; set; }
[Column("ClienteId")]
public Entidad Cliente { get; set; }
public int UbicacionId { get; set; }
public Ubicacion Ubicacion { get; set; }
public int ProductoId { get; set; }
public Producto Producto { get; set; }
public int Lunes { get; set; }
public int Martes { get; set; }
public int Miercoles { get; set; }
public int Jueves { get; set; }
public int Viernes { get; set; }
public int Sabado { get; set; }
public int Domingo { get; set; }
public AppUsuario Usuario { get; set; }
}
这是我的api中的一条路线。
[HttpPut("{programacionsemanalId}")]
public async Task<IActionResult> Put(int programacionSemanalId, [FromBody] ProgramacionSemanalViewModel model)
{
try
{
var oldProgramacionSemanal = await _repository.GetProgramacionSemanalAsync(programacionSemanalId);
if (oldProgramacionSemanal == null) return NotFound($"No se encontro la Programación Semanal.");
_mapper.Map(model, oldProgramacionSemanal);
var currentUser = await _userManager.FindByNameAsync(User.Identity.Name);
foreach (var item in oldProgramacionSemanal.ProgramacionSemanalDetalles)
{
var producto = await _repository.GetProductoAsync(item.ProductoId);
if (producto == null) return BadRequest();
item.Producto = producto;
var ubicacion = await _repository.GetUbicacionAsync(item.UbicacionId);
if (ubicacion == null) return BadRequest();
item.Ubicacion = ubicacion;
item.Usuario = currentUser;
}
if (await _repository.SaveAllAsync())
{
return Ok(_mapper.Map<ProgramacionSemanalViewModel>(oldProgramacionSemanal));
}
}
catch (Exception ex)
{
_logger.LogError($"Threw exception while updating: {ex}");
}
return BadRequest("Couldn't update");
}
我认为一切正常,
1)我收到了模型对象中定义的所有信息。
2)我从对象oldProgramacionSemanal
中获取db的所有信息3)调用_mapper.map后,修改了对象信息oldProgramacionSemanal,将关系值设置为null,但是Cliente
5)当它试图保存对象时,我收到此错误
{System.InvalidOperationException:实体类型的实例&#39; ProgramacionSemanalDetalle&#39;无法跟踪,因为另一个具有键值的实例&#39; {ProgramacionSemanalDetalleId:38}&#39;已被跟踪。附加现有实体时,请确保仅附加具有给定键值的一个实体实例。 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap
1.ThrowIdentityConflict(InternalEntityEntry entry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap
1.Add(TKey key,InternalEntityEntry entry,Boolean updateDuplicate) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState,EntityState newState,Boolean acceptChanges) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState,Boolean acceptChanges,Nullable1 forceStateWhenUnknownKey) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode node, Boolean force) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode node, TState state, Func
3 handleNode) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry,EntityState entityState,Boolean forceStateWhenUnknownKey) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.NavigationCollectionChanged(InternalEntityEntry条目,INAVigation导航,IEnumerable1 added, IEnumerable
1已删除) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.NavigationCollectionChanged(InternalEntityEntry条目,INAVigation导航,IEnumerable1 added, IEnumerable
1已删除) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectNavigationChange(InternalEntityEntry条目,导航导航) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(InternalEntityEntry条目) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(IStateManager stateManager) 在Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges() 在Microsoft.EntityFrameworkCore.DbContext.TryDetectChanges() 在Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess,CancellationToken cancellationToken) at C:\ gleintech \ GasApp \ GasApp.Data \ GasRepository.cs中的GasApp.Data.GasRepository.SaveAllAsync():第37行 at GasApp.Controllers.ProgramacionSemanalController.Put(Int32 programacionSemanalId,ProgramacionSemanalViewModel model)in C:\ gleintech \ GasApp \ GasApp \ Controllers \ ProgramacionSemanalController.cs:line 171}
有人能就我做错了什么给我任何建议吗?
阿尔贝托
答案 0 :(得分:2)
您遇到的错误与EF Core 2.0中的问题有关 - 请参阅https://github.com/aspnet/EntityFrameworkCore/issues/7340。如果您尝试使用具有相同主键的新实体类替换实体类,则会发生这种情况。
这会在您的代码中发生,因为您更改了producto / ubicacion导航属性,告知EF更新它们。 EF通过(尝试)删除指向的现有实体并将其替换为刚刚加载的实体来实现此目的。然后,EF Core 2.0中的限制会引发您发现的错误。
我不完全确定你要做什么,因为我不知道你的存储库在做什么 - 它是否正在读取集合,是否跟踪了所有实体,你是否包括producto / ubicacion?因此,我不能给你一个确定的答案,但至少你现在知道你为什么会得到这个错误。
注意:#7340问题(我报告的)已在2.1中修复,因此这可行,但效率低,因为您删除/添加没有或几乎没有变化的关系。如果没有对producto / ubicacion进行任何更改,那么您可以考虑使用IsModified方法告诉EF他们没有更改它将保留原始数据,例如
context.Entry(entity).Navigation("PropertyName").IsModified = false;
我相信这有帮助。
答案 1 :(得分:0)
当您查询以后想要更新它的实体时,会触发此异常。例如,您在ProgramacionSemanalDetalle
api中检索了标识为38
的{{1}}实例,但在Get
api中,您正在对从viewmodel映射的模型进行更改,而不是实际模型由EF跟踪。
Put