C# 创建DTO时如何避免冗余业务逻辑(DB抓取)?

C# 创建DTO时如何避免冗余业务逻辑(DB抓取)?,c#,architecture,n-tier-architecture,design-principles,C#,Architecture,N Tier Architecture,Design Principles,我正在用C#开发N层应用程序。服务器端由以下几层组成: 数据访问层(EF代码优先实体和DbContext) 业务层(包含所有业务逻辑和对象) WCF服务层(每调用一个实例服务,从业务层公开一些操作) 现在,客户端请求的处理方式如下: 客户端创建请求DTO并将其发送到服务层 服务层将此DTO映射到业务对象并调用BL方法 业务层做一些有用的事情,向DAL发出请求,然后将一些业务对象返回给服务 服务层将业务对象映射到DTO响应并返回到客户端 尽管Automapper减少了代码重复,但它仍然工作得很

我正在用C#开发N层应用程序。服务器端由以下几层组成:

  • 数据访问层(EF代码优先实体和DbContext)
  • 业务层(包含所有业务逻辑和对象)
  • WCF服务层(每调用一个实例服务,从业务层公开一些操作)
现在,客户端请求的处理方式如下:

  • 客户端创建请求DTO并将其发送到服务层
  • 服务层将此DTO映射到业务对象并调用BL方法
  • 业务层做一些有用的事情,向DAL发出请求,然后将一些业务对象返回给服务
  • 服务层将业务对象映射到DTO响应并返回到客户端
  • 尽管Automapper减少了代码重复,但它仍然工作得很好。实际问题是:

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

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

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


    我通常返回业务实体的不同表示形式,具体取决于在BL中执行的操作类型。例如,在搜索返回时,返回用户的搜索表示形式,其中仅包含用户身份所需的最小属性集。获取特定用户时,我返回一个完整的业务对象


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

    • DTO:负责传输用户并在业务层和消费者之间创建松散耦合
    • BO:负责封装和执行业务操作
    • DB实体:负责使BO对象持久化

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

    您是否考虑过在客户端上使用一些缓存?尤其是当您再次从服务层获得相同的信息时。这些数据的波动性有多大?“我通常会根据BL中的操作类型返回不同的业务实体表示形式。”我想这就是我要做的。无论如何,BL中都会有一些分页\排序逻辑,即使它不是纯域逻辑(或者我错了?)“关于代码复制的问题。这不是复制。用户的不同表示有不同的责任。”这正是我在为不同层制作不同对象时的想法,即使这些对象看起来非常相似。我没有在问题中解释它,因为它有点超出了问题的范围。我提到它是因为一些开发人员不喜欢它,认为它违反了DRY原则。你们也知道这一点,这很好。就像你一样,我遇到了一些想要使用相同对象的开发人员。