提问人:pantonis 提问时间:10/12/2023 最后编辑:Svyatoslav Danylivpantonis 更新时间:10/12/2023 访问量:46
EF Core SaveChangesInterceptor 引发无法跟踪实体类型的实例,因为具有相同键的此类型的另一个实例已存在
EF Core SaveChangesInterceptor throws The instance of entity type cannot be tracked because another instance of this type with the same key is already
问:
我在 EF Core 7 中有以下拦截器,它试图删除 IEnumEntity 类型的重复条目,并将相同的 ID 添加到 ChangeTracker。但是,当我调用SaveChanges时,在调用此代码时仍然收到错误The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked
var trackedEntities = context.ChangeTracker.Entries<IEnumEntity>()...
为什么我还没有得到这个,因为还没有被召唤?base.SavingChangesAsync(eventData, result, cancellationToken)
public class EnumEntitySaveInterceptor : SaveChangesInterceptor
{
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
InterceptionResult<int> result,
CancellationToken cancellationToken = default)
{
var context = eventData.Context;
// Get a list of all added and modified entities grouped by their type and Id
var trackedEntities = context.ChangeTracker.Entries<IEnumEntity>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
.GroupBy(e => new { Type = e.Entity.GetType(), Id = GetEntityId(e.Entity) });
// Loop through each group of entities with the same Type and Id
foreach (var group in trackedEntities)
{
// If there are multiple entities with the same Type and Id,
// detach all but the first one
var entitiesToDetach = group.Skip(1).ToList();
foreach (var entry in entitiesToDetach)
{
entry.State = EntityState.Detached;
}
}
return base.SavingChangesAsync(eventData, result, cancellationToken);
}
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
.... same logic as SavingChangesAsync
}
private int GetEntityId(object entity)
{
var type = entity.GetType();
var idProperty = type.GetProperty("Id");
if (idProperty != null && idProperty.PropertyType == typeof(int))
{
return (int)idProperty.GetValue(entity);
}
throw new InvalidOperationException($"Entity type {type} does not have an Id property of type int.");
}
}
以及异常的堆栈跟踪
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey, Nullable`1 fallbackState)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.NavigationCollectionChanged(InternalEntityEntry entry, INavigationBase navigationBase, IEnumerable`1 added, IEnumerable`1 removed)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.NavigationCollectionChanged(InternalEntityEntry entry, INavigationBase navigationBase, IEnumerable`1 added, IEnumerable`1 removed)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectNavigationChange(InternalEntityEntry entry, INavigationBase navigationBase)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.LocalDetectChanges(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(IStateManager stateManager)
at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges()
at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.TryDetectChanges()
at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.Entries[TEntity]()
at MyProject.EntityFramework.Inteceptors.EnumEntitySaveInterceptor.SavingChangesAsync(DbContextEventData eventData, InterceptionResult`1 result, CancellationToken cancellationToken) in C:\Github\........
at Microsoft.EntityFrameworkCore.Diagnostics.CoreLoggerExtensions.SaveChangesStartingAsync(IDiagnosticsLogger`1 diagnostics, DbContext context, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__64.MoveNext()
答: 暂无答案
评论
ChangeTracker
SaveChangesInterceptor