EF Core SaveChangesInterceptor 主键下一个值

问题描述 投票:0回答:1

我已经从

SavingChangesAsync
接口实现了
ISaveChangesInterceptor
。我无法确定正在保存的记录的主键,因为它尚未提交。我也尝试了
SavedChangesAsync
功能,但是实体状态没有设置为
Added
,而是
Unchanged

我尝试了以下方法:

public async ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
    var entry eventData.Context!.ChangeTracker.Entries().FirstOrDefault()
    
    console.write(entry.State); //equals Added
    console.write(entry.IsKeySet); //equals false
    console.write(entry.Entity.Id); //equals 0
    
    return await new ValueTask<int>(result);
}

记录的下一个主键值尚未设置。我也用过:

public async ValueTask<int> SavedChangesAsync(SaveChangesCompletedEventData eventData, int result, CancellationToken cancellationToken = default)
{
    var entry eventData.Context!.ChangeTracker.Entries().FirstOrDefault()
    
    console.write(entry.State); //equals Unchanged
    console.write(entry.IsKeySet); //equals true
    console.write(entry.Entity.Id); //equals next integer value

    return await new ValueTask<int>(result);
}

我无法使用新 id 触发第一个事件,也无法使用状态值为

Added

触发第二个事件
c# entity-framework-core interceptor
1个回答
0
投票

这是处理数据库生成的标识列时的预期行为。在

SavingChanges
时,您可以查询更改跟踪器以查看添加、更新或删除的内容。在 SavedChanges 时,更改已提交,因此更改跟踪器会将它们报告为未修改。

这意味着,如果您想记录有关实体的信息并在插入时包含其结果 ID,则需要缓存对添加的实体的引用以及任何“预提交”状态(如果您在 SavingChanges 事件处理程序期间记录该内容) 。然后在

SavedChanges
处理程序中,从缓存的引用中获取 Id 和详细信息:

private class EntityChangeInfo
{ 
    public EntityState State { get; set; }
    public EntityEntry Entry { get; set; }
    // This is where you can add things like field data for updates, old value / updated value, etc.
}

private List<EntityChangeInfo> _entityChanges = new();

...然后在 SavingChanges() 中

_entityChanges.Clear();
var entry eventData.Context!.ChangeTracker.Entries().FirstOrDefault()

_entityChanges.Add(new EntityChangeInfo { entry.State, entry });
return await new ValueTask<int>(result);

然后在SavedChanges()中

foreach(var entityChange in _entityChanges)
{
   console.write(entityChange.State); // Original state when saving
   console.write(entityChange.Entry.Id); equals key that was assigned
}

_entityChanges.Clear();

在提交之前尝试获取 ID 的麻烦在于,这只能通过 EF 在数据库使用的序列上应用并发锁来完成,从您查询下一个可用的时间开始ID 是,并且正在提交更改。这会带来问题,因为您可以获得 ID 值,但提交实际上会失败。因此,仅应在提交发生后才对此进行报告/审核。

© www.soinside.com 2019 - 2024. All rights reserved.