从数据库中获取插入 ID 的问题

Problem with getting inserted Id from database

我试图通过 Entity Framework 从数据库中获取最后插入的 ID,但是我的问题有点独特,我找不到任何解决方案,只能重写我的整个基础架构和业务层,所以我所有的 ID 都是 Guid,我可以手动创建,或者在提交后通过另一个数据库调用获取最后一条记录。

问题来了。我有一个三层架构,我在其中使用 UoW、存储库、服务和外观。我会从上到下展示我的代码,这样你就明白了。

这是我的门面,uow.Commit 正在调用 SaveChanges()

public async Task<int> RegisterUserAsync(UserCreateDto user)
{
        using (var uow = UnitOfWorkProvider.Create())
        {
            var id = _userService.Create(user);
            await uow.Commit();
            return id;
        }
}

如你所见,我只将我的 DTO 发送到服务中,我的处理过程是这样的,我也在服务内部进行映射

public virtual int Create(TCreateDto entityDto)
{
        var entity = Mapper.Map<TEntity>(entityDto);
        Repository.Create(entity);
        return entity.Id;
}

最后我的存储库看起来像这样

public TKey Create(TEntity entity)
{
        Context.Set<TEntity>().Add(entity);
        return entity.Id;
}

是否有一些优雅的解决方案?就像我说的,我唯一的想法是将所有 ID 切换为 Guid 或在提交后第二次调用 Id,我发现这不是很好的解决方案,因为当我想在一个事务中连接两个或多个表时,这是不可能的。

问题的 EF Core 解决方案很简单 - 实体实例的自动生成 PK 可用 调用 SaveChanges[Async] 之后。例如

var entity = Mapper.Map<TEntity>(entityDto);
Context.Add(entity);
// Here entity.Id contains auto-generated temporary value
// Other stuff...
Context.SaveChanges();
// Here entity.Id contains actual auto-generated value from the db

所以问题更多地出在基础设施的设计上——所有这些(不必要的)UoW、存储库、服务和外观都只是隐藏了该功能。

我在您的架构中看到的唯一相对简单和优雅的解决方案是将服务 return 类型从 int 更改为 Func<int>,例如

public virtual Func<int> Create(TCreateDto entityDto)
{
    var entity = Mapper.Map<TEntity>(entityDto);
    Repository.Create(entity);
    return () => entity.Id; // <--
}

然后在您的外观中您可以使用

public async Task<int> RegisterUserAsync(UserCreateDto user)
{
    using (var uow = UnitOfWorkProvider.Create())
    {
        var id = _userService.Create(user);
        await uow.Commit();
        return id(); // <-- the actual id!
    }
}

编辑:

实际上,EF Core 提供了另一种选择,它允许您保持当前设计的完整性 - HiLo key generation strategy, but only if the database provider supports it. I can say for sure Microsoft.EntityFrameworkCore.SqlServer and Npgsql.EntityFrameworkCore.PostgreSQL 分别通过 ForSqlServerUseSequenceHiLoForNpgsqlUseSequenceHiLo 流畅的 API 支持它。