从数据库插入ID的问题

时间:2019-04-24 17:55:49

标签: c# entity-framework asp.net-core .net-core ef-core-2.2

我试图通过Entity Framework从数据库中获取最后插入的ID,但是我的问题在某种程度上是唯一的,我无法找到任何解决方案,而是重写了整个基础结构和业务层,因此我的所有ID都是Guid ,我可以手动创建,或者在提交后通过另一个数据库调用获取最新记录。

这是问题所在。我有一个三层体系结构,在其中使用UoW,存储库,服务和外观。我将自上而下显示我的代码,以便您理解。

这是我的门面,SELECT datum, alldata.worker_id, reporting_plan.project_id, SUM(effort::float)/60/60 FROM (SELECT DISTINCT datum, worker_id FROM (select *, generate_series(start, end, '1 day'::interval) as datum from reporting_plan) ) AS alldata LEFT OUTER JOIN reporting_plan ON alldata.worker_id = reporting_plan.worker_id GROUP BY datum, alldata.worker_id, reporting_plan.worker_id, reporting_plan.project_id ORDER BY datum, alldata.worker_id, reporting_plan.worker_id, reporting_plan.project_id 在呼叫uow.Commit

SaveChanges()

如您所见,我仅将DTO发送到服务中,我在其中进行处理,也正在服务内部进行映射

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

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

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

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

1 个答案:

答案 0 :(得分:5)

该问题的EF核心解决方案很简单-调用import io.undertow.Handlers; import io.undertow.Undertow; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.BlockingHandler; public static void main(String[] args) { Undertow server = Undertow.builder() .addHttpListener(8087, "xx.xx.xx.xx") .setHandler(Handlers.pathTemplate().add("/webhook", new BlockingHandler(new ItemHandler()))) .build(); server.start(); } static class ItemHandler implements HttpHandler { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { exchange.getInputStream()); } } 后可以使用实体实例的自动生成的PK。例如

SaveChanges[Async]

因此,问题更多在基础架构的设计中-所有这些(不必要的)UoW,存储库,服务和外观都只是隐藏了该功能。

我在您的体系结构上看到的唯一相对简单而优雅的解决方案是将服务返回类型从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 更改为int,例如

Func<int>

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

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

编辑:

实际上,EF Core提供了另一个选项,可以使您的当前设计保持完整-HiLo key generation strategy,但前提是database provider支持。我可以肯定地说Microsoft.EntityFrameworkCore.SqlServerNpgsql.EntityFrameworkCore.PostgreSQL确实支持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! } } ForSqlServerUseSequenceHiLo流利的API。