在saveChanges之后如何使用DbContextScope检索数据库生成的ID

时间:2019-04-20 18:44:51

标签: c# entity-framework

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

  • 演示文稿:与我的问题无关。
  • 业务:在这一层中,我计划仅使用DTO对象。我想将我的业务层与任何数据库实现细节分开,因此与实体的所有交互都在DAL层中完成。
  • DAL :在这一层中,我计划拥有所有实体框架代码和实体。我将介绍可以由业务层调用的存储库。这些存储库期望DTO对象作为输入,并返回DTO对象作为输出。 DTO和实体之间的映射是在此层完成的。

我看了很多与Entity Framework相关的在线教程和文章,并遇到了 DbContextScope 项目,该项目似乎是控制“业务交易”并确保所有相关更改的非常好的解决方案提交或回滚。参见GitHub:https://github.com/mehdime/DbContextScope

该GitHub存储库中的演示包含一个场景,其中在数据库中创建了一个新实体。当我尝试将该场景映射到我的图层时,它看起来像这样:

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

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

  3. 业务:在 DbContextScope 上调用SaveChanges()方法,该方法又在实体框架的DbContext上调用SaveChanges()。

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

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

关于如何解决此问题的任何建议,或者您对我的图层是否建议其他方法? (例如,在业务层中也使用实体-尽管听起来做错事了)

1 个答案:

答案 0 :(得分:0)

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

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

可能有一个更为纯粹的论点,认为这会将域或EF特定问题的细节“泄漏”到控制器中,但是我个人的看法是,“信任”实体和EF在有限上下文范围内的好处服务层远远超过其他任何东西。它更简单,并且为您的代码提供了很大的灵活性,而无需使用几乎重复的方法来向消费者提供过滤后的数据,也不需要复杂的过滤逻辑来从服务层“隐藏” EF。我遵循的基本规则是实体绝不会在其上下文范围的边界之外返回。 (无需分离/重新附加,只需选择进入ViewModels,并根据传入的视图模型/参数管理实体上的Create / Update / Delete。)

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