【问题标题】:N-Tier architecture with DAL, Repo, Service, API layers: what type of objects should each layer deal in/out + where should validation/mapping occur?具有 DAL、Repo、Service、API 层的 N 层架构:每个层应该处理/输出什么类型的对象 + 应该在哪里进行验证/映射?
【发布时间】:2014-07-05 06:50:54
【问题描述】:

我认为我的应用程序至少应该有以下几层:

  • DAL(无通用接口;从数据库获取数据,从另一个 Web 服务获取数据,从文件获取数据)
  • 存储库(每个重要/根聚合的 CRUD 接口;实现因源而异)
  • 服务(使用存储库接口;实现因业务逻辑而异)
  • Web API(包装服务;安装容器;实现因运行时参数/配置而异)

我知道我的 Web API 应该返回 DTO,我将其解释为只有自动实现的公共属性的 C# 对象。

理论上,有时我需要执行BigComplicatedServiceCommand,其中一个工作单元中将涉及多个存储库,但其他时候我的 Web API 还不如直接调用存储库,因为它只是在执行 CRUD。

我有兴趣了解从(通过 web api 模型绑定输入到 web 服务)DTO 到服务需要的任何地方的位置映射,以及应该在哪里进行验证。 p>

粗略地说,我有这个想法:

输入接口

  1. 接收请求并映射到路线
  2. 使用模型绑定器按约定绑定到 DTO
  3. 使用 IoC 容器实例化特定控制器
  4. 运行特定的控制器操作
  5. 在控制器操作中,包装对服务层的调用

现在,在第 5 步之后出现问题。我是否将 DTO 发送到服务?然后,我的服务将与我的 DTO 相结合。

我是否为每个服务方法定义了一个特定的接口?如果是这样,这些实际上是它们自己的 DTO,我不妨为每个服务输入排列定义一个 DTO。

假设我的服务采用 DTO,

  1. 在服务方法中,执行业务逻辑并调用存储库
  2. 在存储库中,CRUD 的东西
  3. 将最终结果从服务方法返回给 API
  4. 转换为 DTO 并从 API 返回到 Internet

现在,我的存储库是否应该严格处理域对象?如果是这样,谁负责选角? (服务?)

最后,考虑到验证,我在想:

  • 使用以下方法之一预先验证:ModelStateActionFilter(在操作执行之前),在转换为服务需要作为输入的任何内容期间。因此,这将确保CreateUserService 正在接收具有UsernamePassword 的对象。
  • 使用存储库和其他用户名唯一且密码足够强的服务在服务方法中验证
  • 在 DAL 级别进行验证以确保 Entity Framework 满意

我的问题是,我应该将 System.DataAnnotations 放在哪些(如果有)对象上?此堆栈中是否有任何类型的模型应负责其自身的验证?

感谢任何哲学帮助。

【问题讨论】:

  • 这个问题应该在programmers.stackexchange.com上

标签: c# web-services validation castle-windsor n-tier-architecture


【解决方案1】:

这个问题...

由于您的问题很长,我可能会错过一些要点,但我们开始吧。顺便说一句,这都是“在我看来”,您应该根据自己的需要进行更改以更好地满足您的需求。

  1. 去掉“N-Tier”这个词。这些天很酷的孩子正在使用“洋葱架构”。

  2. 从“核心”项目开始。这是您所有核心对象所在的位置。您将拥有一个客户、一个订单、一个产品等。在这个级别上,不要担心数据库、Web API 或 UI。你的对象应该有方法、属性和行为。这里的一切都不应该是Public { get; set; }。哦,如果您在这里没有明确需要接口,请不要使用它们。

  3. 完成“核心”项目后,您可以考虑如何存储这些对象。您可以创建一个“存储库/DAL”项目。您的存储库应该包含您的聚合根。弄清楚如何将其放入数据库是工作。

  4. 现在是“服务”项目。服务很简单。您的服务负责:从存储库获取对象、调用对象的方法、将对象放回存储库。现在,您的服务可以返回或接受“核心”对象,或者公开它们自己的 DTO。

  5. 您的 WEB API / MVC 项目将与用户进行交互。它会调用 Service 来获取它想要的任何东西。在这里,您可以使用 View Models 而不是 Core 对象来呈现给用户。

-- 好吧--

但这里有一些对您问题的明确回答:

  1. Web Api 不应该直接调用存储库。

  2. 从您的服务返回到 Web Api DTO/视图模型的任何映射都应该发生在 Web Api 项目中。

  3. 验证:Web Api 可以验证所有内容以帮助用户。此外,Core 应该很好地验证,核心的东西等等......验证将在很多地方结束。

  4. 不要为每个服务定义接口。如果只有一个实现,它可能不应该是一个接口。

  5. 在服务方法中,你不做业务逻辑。逻辑进入核心对象。

  6. 是的,存储库严格使用核心/域对象。是的,将它交给他们的服务工作。

  7. System.DataAnnotations 进入 Web Api“视图/模型/DTO”

【讨论】:

  • 业务逻辑进入核心对象?如果返回给用户的数据是不同对象的组合,并且需要一起验证怎么办。业务规则也会影响 UI 本身。那么有没有更好的地方来实施我的业务规则?
  • @IKashef 如果业务规则指定了 UI 的行为方式,那么它根本不应该是业务规则。 UI 应该是业务当前状态的表示。 HTML、按钮、IOS 应用、动画……这些都是代表业务状态的方式。
  • 但这些规则在逻辑上与业务相关。例如,如果产品状态为待处理,则可以编辑或删除。如果状态已售出,则它必须是只读的。这些是业务规则对吗?并且仅在服务器端执行这些规则并不方便。应用程序不应显示禁用的按钮,例如(编辑按钮)它应该首先隐藏。如果您知道在说什么,但仍然认为它们不是业务规则,您能否解释一下与您在回答中建议的架构接近的良好架构?
  • @IKashef 显然这个对话很快就会失控,但是......假设您的业务规则是“如果产品状态为待处理,则可以编辑或删除它”。在这种情况下,您的产品对象可能具有名为CanDeleteCanEdit 的属性。在内部,当您阅读这些内容时,它们只会在状态为 pending 时返回 true。因此 UI 仅根据这些属性隐藏或显示按钮,而不是业务规则本身。
  • 我完全同意。只是想参考您在此处建议的架构得到答案。感谢您的提示,如果我有更多问题,我将发布一个新问题。谢谢
猜你喜欢
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 2013-09-23
  • 1970-01-01
相关资源
最近更新 更多