【问题标题】:Architectural problems in repository pattern and unit of work存储库模式和工作单元中的架构问题
【发布时间】:2019-01-06 20:41:53
【问题描述】:

我已经使用工作单元实现了存储库模式,但存在一些架构问题。

例如,假设我正在创建一个二手汽车零件在线商店。虽然我对我的数据库进行操作,但我也需要对来自不同废料场的远程 API 执行操作,例如需要运行搜索、可用性更新等等...

我决定尝试工作单元和存储库模式

做的事情大多像 Mosh Hamedani 但针对 asp.net core 2.1 From videos like this one

只要我使用 EF(或其他东西与 DB 进行通信),工作单元和存储库就可以正常工作并且有意义,但是如果我要通过不同的 Web api 获取一些数据就没有多大意义. (例如,从处理和重试相似但不同的不同 API 获取市场上的汽车列表 - 我正在按键检索同一接口的不同实现)

第一 我不喜欢我的工作单元中所有存储库的所有实例,但在大多数情况下只需要一个。我知道它有助于重用上下文事务而不将其包装在我自己的中,但仍然有不必要的实例很愚蠢。

第二 我应该在存储库和工作单元内实现远程 api 的检索逻辑和处理,还是放弃工作单元并做其他事情?只保留存储库? (曾经有人提到我不熟悉的外观模式)

我倾向于过度设计事物,现在我很困惑。任何见解都是有帮助的。

【问题讨论】:

    标签: unit-testing asp.net-core repository-pattern unit-of-work


    【解决方案1】:

    虽然我同意 Chris Pratt 的回答,但我认为在某些情况下创建存储库是必要的,即使您使用的是像 EF 这样的 ORM。我已经详细解释了here

    对于您的问题,我建议您应该继续使用 UoW 和 Repository,就像您目前所做的那样。如前所述here UoW 不仅仅是交易。如果您正确使用DbContext,EF 会为您完美实现这一点。

    关于涉及当前存储库和 UoW 中其他来源的 API 的问题,应该分开。我建议您创建单独的包装器来消耗第三方 API 的复杂性。随心所欲地称呼它;存储库或外部 Api 包装器或其他任何东西......

    【讨论】:

    • 我想我们也有类似的想法。放弃了“工作单元”,但保留了存储库,因为我喜欢这种粒度。还希望仅在需要时控制实例和事务。将远程 API 处理分离为一个单独的独立服务,并通过抽象使其看起来像一个 API。所以现在它看起来像这样,例如_vendorAPIManager.GetVendor(Vendor.JacksScrapyard).GetSaleItems()
    • 我们都有一个相似的想法,这一点也不错,但我不得不接受 Chris 的想法作为公认的答案。尽管 Chris 的“从小处着手”的想法在某种程度上与我们的想法相同,但它试图在后期变得更多,而我们会保持整体性,而他不会。感谢我所感激的一切。
    【解决方案2】:

    我使用相同的课程并实施了我的工作单元......但后来,我改变了主意并删除了 UoW 课程。 DbContext 已经在实施 UoW 和存储库模式:From MS Documentation

    DbContext 类

    表示工作单元和存储库模式的组合 并使您能够查询数据库并将更改组合在一起 然后将作为一个单元写回商店。 DbContext 是 概念上类似于 ObjectContext。

    我仍然添加了自己的存储库。我同意 Chris 的观点,DbSet 是一个存储库,但我可以通过添加自己的存储库来添加更专业的方法。

    在您链接的视频中,我们通过将所有存储库放在 UoW 类中来实现 UoW。在我看来,这种实现可能违反了一些 SOLID 原则:

    1. 感觉好像我们违反了开放/封闭原则……因为每次我们添加新的存储库时,我们都需要修改 UoW 类以包含新的存储库。
    2. 感觉我们违反了接口隔离原则。 ISP 声明不应强迫客户端实现他们不使用的接口。 UoW 包含所有存储库的实现......但是消费客户端不需要所有这些实现,客户端可能只需要其中一个。
    3. 感觉我们违反了单一职责原则,因为 UoW 负责这么多存储库。

    【讨论】:

    • “我认为使用另一个 UoW 课程没有什么好处” - 可模拟性可能是其中之一。
    • @guillaume31,感谢您的评论,我已经更新了答案。我认为我们仍然可以模拟存储库...
    【解决方案3】:

    存储库模式仅用于一个目的:从您的应用程序代码中抽象出 SQL。工作单元模式的存在只是为了支持和协调具有多个存储库的事务操作。 EF 和其他 ORM 为您处理所有这些。特别是对于 EF,每个DbSet 都是一个存储库,DbContext 是工作单元。当您使用像 EF 这样的 ORM 时,that 是您的数据层,而不是您可能传统上创建的一些自定义类库。您绝对应该在 EF 之类的基础上实现存储库/工作单元模式。

    您正在寻找的本质上是一个 API 网关。在微服务架构中,每个服务处理一个离散的功能单元,这意味着使用许多(如果不是全部)这些微服务的横切应用程序将具有大量的依赖关系。最典型的方法是创建一个或多个 API 网关,它们本质上将与微服务的所有或特定子集的通信打包。您的应用程序仅直接与 API 网关对话,API 网关协调与促进应用程序请求所需的所有微服务的通信。这进一步允许您以无缝方式实现消息队列等层。

    【讨论】:

    • 有道理,我听说过,但直到现在还没有时间跟进。 你知道从哪里开始最好吗?比如链接、视频、示例?我是一个自我思考的开发者,所以我的知识有点缺乏组织,这就是为什么我试图在我去的时候填补它,我想现在是微服务架构的时候了。克里斯,你帮了我很多,所以非常感谢你,我的意思不仅仅是这个问题,而是多年来其他几个问题。
    • 您绝对不应该在 EF 之类的东西之上实现存储库/工作单元模式 - EF 应该是您的业务层声明的存储库的实现细节。如果您决定将数据保存在某些 xml 文件中或将数据库放在某些 Web API 后面,您肯定不想实现一大堆 DbContext/DbSet
    • 好的,昨晚我已经阅读了微服务架构并观看了一些视频,但对于一个小型应用程序来说,它看起来工作量更大而且有点矫枉过正?我错过了什么吗?据我了解,我需要在能够相互独立运行的独立服务中分离功能,然后我需要提供身份验证服务,该服务将作为身份提供者或其他东西,并以某种方式对所有用户进行身份验证,我并不完全确定该怎么做。然后还有docker……可能是我想多了?
    • 简单地说,是的。但是,您可以遵循微服务的精神,而不必一路走下去。首先,只有当它们被公开时才需要进行身份验证。如果您将它们全部放在内部防火墙之后,特别是如果应用程序仅与网关而不是每个单独的服务进行通信,则它们不一定需要授权层。即使这样,您也不会在每个微服务上授权单个用户,而是授权一个客户端(即您的应用程序)。您将授予应用程序一个客户端 ID 和密码,然后它会使用它来授权其请求。
    • 最后,您可以从小处着手,基本上只用代码创建这个基础设施。换句话说,每个微服务可能只是一个类,其方法模仿真实微服务上的 API 端点。同样,您的 API 网关也可以只是一个将“微服务”类作为依赖项并将它们包装在一个整齐的蝴蝶结中以用于应用程序目的的类。只要你遵循微服务的设计理念,这将导致整齐有序和抽象的代码,如果你最终确实创建了成熟的微服务,那么从那里开始会容易得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多