创建DTO时如何避免冗余业务逻辑(DB fetching)?

How to avoid redundant business logic (DB fetching) when creating DTO?

我正在用 C# 开发 N 层应用程序。服务器端包含以下层:

现在客户端请求是这样处理的:

  1. 客户端创建请求DTO并将其发送到服务层
  2. 服务层将此DTO映射到业务对象并调用BL方法
  3. 业务层做一些有用的事情,向 DAL 发出请求,然后 returns 一些业务对象来服务
  4. 服务层将业务对象映射到 DTO 响应,并将 returns 映射到客户端

尽管 Automapper 减少了代码重复,但它工作得很好。实际问题是这样的:

客户端在不同的视图中显示相同的对象:网格、表单等。例如,网格(列表)视图只需要来自用户对象的 Id 和名称,而表单(详细信息)视图需要每个用户的 属性 .但是业务层对视图一无所知。它只能向服务调用提供完整的 UserBL 对象,然后由服务负责将此 UserBL 映射到 UserListDto 或 UserDetailsDto。对于一些重对象,从数据库中获取额外的字段会成为性能问题。

那么,业务层是否应该为不同的客户端操作提供不同的方法呢?我不喜欢这个解决方案,因为它看起来像域逻辑污染,但我不知道还能做什么。

Client shows same objects in different views: grid, form, etc. For example, grid(list) view requires only Id and Name from User object, while Form(details) view needs every User's property. But Business layer knows nothing about views. It can only provide full UserBL object to Service calls and then it's the Service responsibility to map this UserBL to UserListDto or UserDetailsDto. And for some heavy objects, fetching extra fields from DB become a performance issue.

我通常 return 业务实体的不同表示形式取决于在 BL 中执行的操作类型。例如,当搜索 return 用户的搜索表示时,它只包含 identity 用户所需的最少属性集。获取特定用户时,我 return 一个完整的业务对象。

关于您的代码重复问题。这不是重复。用户的这些不同表示具有不同的 责任

  • DTO:负责传递一个用户,在业务层和消费者之间建立松耦合
  • BO:负责封装和执行业务操作
  • DB实体:负责使BO对象持久化无知

因此,如果您只使用一个用户的一种表示,您将合并所有这些责任,因此必须牺牲良好的设计才能让每个人都能使用它。唯一真正的好处是你必须少写几行代码。当您开始维护已发布的应用程序时,请记住这一点。您节省了几行代码,但维护起来却困难得多。