C# 如何使用DbContextScope检索saveChanges后由DB生成的ID

C# 如何使用DbContextScope检索saveChanges后由DB生成的ID,c#,entity-framework,C#,Entity Framework,我计划创建一个具有以下层的应用程序,并使用实体框架作为我的ORM: 陈述:与我的问题无关 业务:在这个层中,我计划只使用DTO对象。我希望将我的业务层与任何数据库实现细节分离,因此与实体的所有交互都在DAL层中完成 DAL:在这一层中,我计划拥有所有实体框架代码和实体。我将介绍可由业务层调用的存储库。这些存储库期望DTO对象作为输入,并返回DTO对象作为输出。DTO和实体之间的映射在此层中完成 我已经阅读了相当多的在线教程和与Entity Framework相关的文章,并偶然发现了DbCon

我计划创建一个具有以下层的应用程序,并使用实体框架作为我的ORM:

  • 陈述:与我的问题无关
  • 业务:在这个层中,我计划只使用DTO对象。我希望将我的业务层与任何数据库实现细节分离,因此与实体的所有交互都在DAL层中完成
  • DAL:在这一层中,我计划拥有所有实体框架代码和实体。我将介绍可由业务层调用的存储库。这些存储库期望DTO对象作为输入,并返回DTO对象作为输出。DTO和实体之间的映射在此层中完成
我已经阅读了相当多的在线教程和与Entity Framework相关的文章,并偶然发现了DbContextScope项目,它似乎是控制“业务事务”并确保提交或回滚所有相关更改的非常好的解决方案。参见GitHub:

GitHub存储库中的演示包含在数据库中创建新实体的场景。当我尝试将该场景映射到我的层时,它似乎是这样的:

  • 业务:使用要存储的实体的属性值创建DTO。在传递DTO的DAL层中创建新的DbContextScope和调用存储库

  • DAL:存储库将DTO映射到实体,并将其添加到实体框架的DbContext中

  • 业务:在DbContextScope上调用SaveChanges()方法,然后在实体框架的DbContext上调用SaveChanges()

  • 在演示中,创建DTO时,已知道所存储实体的ID。但是,我正在寻找一种方法,在业务层中调用DbContextScope上的SaveChanges()方法后,确定EF自动分配的ID。由于此时我在业务层,我不再有权访问该实体,因此我无法再访问该实体的ID属性

    我想我只能通过查询数据库中刚刚创建的记录来确定ID,但这只有在原始DTO包含一些我可以用来查询数据库的唯一标识符时才可能。但是,如果我的DTO中没有唯一的值可以用来查询,该怎么办


    关于如何解决这个问题,你有什么建议吗?或者你有没有为我的图层推荐一种替代方法?(例如,在业务层中也使用实体——尽管这听起来是错误的)

    我尽可能地使用Mehdime的上下文范围,因为我发现它是一个工作单元的特殊实现。我同意卡米洛关于不必要的分离的评论。如果EF被信任作为您的DAL,那么它应该被信任按照设计工作,以便您可以完全利用它

    在我的例子中,我的控制器管理DbContextScope,我将存储库模式与实体的DDD设计结合使用。存储库充当与DbContextLocator的上下文范围和位置的交互的守门人。当涉及到创建实体时,存储库充当具有“Create{X}”方法的工厂,{X}表示实体。这样可以确保提供创建实体所需的所有信息,并且在返回实体之前将实体与DbContext关联,从而确保实体始终处于有效状态。这意味着,在进行上下文范围SaveChanges调用时,绑定服务将自动拥有分配了ID的实体。ViewModels/DTO是控制器返回给使用者的内容。您还可以选择在DbContextScope的边界内调用DbContext的SaveChanges,这也将在上下文范围SaveChanges之前显示ID。当您想要获取松散耦合实体的ID时,这更像是一个非常边缘的场景。(无FK/映射关系)存储库还提供“删除”代码,以确保管理所有相关实体、规则等。而编辑实体属于实体本身的DDD方法

    可能有一种更纯粹的观点认为,这会“泄露”域或特定于EF的关注点的细节到控制器中,但我个人的观点是,在服务层的有限上下文范围内“信任”实体和EF的好处远远超过任何其他好处。它更简单,并且允许您在代码中具有很大的灵活性,而不需要传播几乎重复的方法来向使用者提供过滤数据,也不需要复杂的过滤逻辑来从服务层“隐藏”EF。我遵循的基本规则是,实体永远不会返回到其上下文范围的边界之外。(无需分离/重新附着,只需选择进入视图模型,并根据传入的视图模型/参数管理实体的创建/更新/删除。)


    如果您可以提供更多具体的问题/示例,请随意添加一些代码,概述您看到这些问题的地方。

    好的,如果业务层负责处理数据访问事务,我看不到业务层和DA层之间的分离,两者都将完全与EF绑定。DAL甚至不应该映射DTO>entity>DTO。除非您计划在其他地方使用DAL,否则我建议您放弃Well的过时架构副本,让业务层负责完成业务事务并将所有更改提交到数据库,这不是很奇怪吗?尤其是当多个后续操作一起形成1个业务事务时?至少在EF Core 3.1中(但我认为它是在这之前引入的),实体的ID属性填充在
    SaveChanges
    上。这难道不能解决您的问题吗?或者,完全避免这个问题,并使用代码生成的ID。确保使用