gpt4 book ai didi

c# - DTO 应该由域实体生成还是由持久性生成?

转载 作者:太空狗 更新时间:2023-10-30 01:33:14 24 4
gpt4 key购买 nike

当谈到使用现代 ORM 的分层应用程序时,我常常不确定应该如何创建特定类以遵守所谓的“最佳实践”,同时还要注意性能要求。

考虑到您在应用程序中可能有任意数量的以下类型的对象:

  1. 域实体 - 这些是包含业务逻辑(对吗?)的丰富类,并且根据 ORM 功能,可能直接与持久性设计相关。

  2. DTO - 这些是更简单的类,它们剥离业务逻辑以便将数据传递给内部和外部客户端。有时这些是扁平的,但并非总是如此。

  3. View Models - 它们与 DTO 相似,因为它们更简单且没有业务逻辑,但它们通常非常扁平并且通常包含与它们的 UI 相关的额外位正在服务。

我面临的挑战是,在某些情况下,将域实体或任何面向持久性的类映射到 DTO 或 ViewModel 等更简单的实体会阻止您进行重要的性能优化。

例如:

假设我有一些如下所示的域实体:

public class Event
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime EventDate { get; set; }

// These would be reference types in most ORMs
// Pretend in the setter I have logic to ensure the headliner =/= the opener
public Band Headliner { get; set; }
public Band Opener { get; set; }
}

public class Band
{
public int Id { get; set; }
public string Name { get; set; }
public Genre Genre { get; set; }
}

在现实世界中,这些可能要复杂得多,具有各种业务逻辑,可能还有一些验证调用等。

如果我公开一个公共(public) API,我的 DTO 可能看起来非常像这个例子,没有任何业务逻辑。

如果我还有一个 MVC 网络应用程序,我想在其中显示事件列表,我可能想要一个看起来像这样的 View 模型:

public class EventViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime EventDate { get; set; }

public int HeadlinerId { get; set; }
public string HeadlinerName { get; set; }
public int OpenerId { get; set; }
public string OpenerName { get; set; }
}

通常,人们只是拉取带有引用的完整域实体,然后使用映射实用程序来混合 View 模型。

但是,假设我有数万条记录。现在 ORM 可能正在创建查询 Storm 来填充完整的引用对象(这可能比这个例子复杂得多,有自己的引用)。性能很快就会开始受到严重影响。

问题是什么?

我知道我不是唯一遇到这个问题的人,所以我很想知道人们如何维护分层应用程序,同时仍然考虑在生成多个对象时保持性能的需要相同的基础域信息

让两个 Event-ish 对象代表相同的持久数据感觉不对,但同时持久层似乎不应该知道 DTO 或 View 模型,否则力争分离有何意义?

那怎么解决呢?持久性是否了解领域实体的严格、详细的表示以及这些实体中数据的轻量级描述?那些更轻量级的描述是 DTO 还是一些域实体精简版?

最佳答案

您的问题没有简单的答案,因为这实际上取决于您希望通过您的架构实现的目标。 这是经典架构的权衡。

这也意味着您需要自己做出决定。确保您了解每种方法的优点和缺点,然后为您的项目做出决定。以下是优缺点列表:

严格分离的优点

  • 能够根据特定层的职责调整和调整结构。例如,持久性 DTO 可以以不同于域实体的方式存储数据,以支持复杂的查询情况。
  • 能够支持数据迁移案例。使用单独的持久性 DTO,您可以选择加载“旧”DTO 格式并将其转换为"new"域实体。
  • 能够简化返回到外部世界的 DTO,例如通过 API。这在使用 DDD 时几乎总是有意义,因为使用 DDD 通常表明领域很复杂。
  • 为开发者更好地分离关注点。通常,严格的分层会增加团队并行处理相同功能的可能性,例如一种在持久性中,一种在领域中。
  • 根据 ORM 或数据库的功能集,直接在持久性中使用域实体甚至不是一种选择。如果它是一个选项,它可能比拥有专用的 DTO 更复杂。

共享类的优点

  • 相同功能的代码更少。
  • 新功能的开发时间通常更快。
  • 更小的概念开销。我认为这是次要的一点,因为 DTO 和 View 模型是众所周知的概念,但这可能是一个问题,具体取决于团队。

如您所见,我不认为性能是共享方法的优势。主要原因是设计良好的对象到对象映射比加载来自数据库的数据。所以我非常有信心严格分离方法中的性能问题是由于其他问题造成的,而不是分层造成的。

有了以上几点(可能还有更多特定于您的环境的点),您应该能够做出决定。我过去曾使用过这两种方法,但对于一定规模的项目,我总是选择严格分离方法。

关于c# - DTO 应该由域实体生成还是由持久性生成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34499929/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com