使用 AutoMapper 从数据库加载实体?

2023-12-24

我读过的大部分内容(例如来自作者 http://lostechies.com/jimmybogard/2009/09/18/the-case-for-two-way-mapping-in-automapper/) 指示应使用 AutoMapper 将实体映射到 DTO。它不应该从数据库加载任何内容。

但如果我有这个怎么办:

public class Customer {
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Order> Orders { get; set; }
}

public class CustomerDto {
  public int Id { get; set; }
  public string Name { get; set; }
  public IEnumerable<int> OrderIds { get; set; }   // here is the problem
}

我需要地图从DTO到实体(即从CustomerDto to Customer),但首先我必须使用该外键列表从数据库加载相应的实体。 AutoMapper 可以通过定制转换器 https://stackoverflow.com/a/3591288/3959480.

我同意这感觉不对……但是还有什么选择呢?将该逻辑粘贴到控制器、服务、存储库、某些管理器类中?所有这些似乎都在将逻辑推向同一层的其他地方。如果我这样做,我还必须手动执行映射!

从 DDD 的角度来看,DTO 不应该是域的一部分。因此 AutoMapper 也不是域的一部分,因为它知道 DTO。所以 AutoMapper 与控制器、服务等处于同一层。

那么,将 DTO 到实体的逻辑(包括访问数据库,并可能抛出异常)放入 AutoMapper 映射中是否有意义?

EDIT
@ChrisSimon 下面的精彩回答从 DDD 的角度解释了为什么我不应该这样做。从非 DDD 的角度来看,是否有令人信服的理由不使用 AutoMapper 从数据库加载?


首先,我将总结一下我对 DDD 中实体的理解:

  1. 实体可以被创建——通常使用工厂。这是它们生命周期的开始。
  2. 可以通过调用实体上的方法来改变实体 - 修改它们的状态。这就是它们在生命周期中不断进步的方式。通过确保实体拥有自己的状态,并且只能通过调用其方法来修改其状态,控制实体状态的逻辑全部位于实体类内,从而实现业务逻辑的更清晰分离和更易于维护的系统。

使用 Automapper 从 Dto 转换为实体意味着实体放弃其状态的所有权。如果 dto 处于无效状态,而您将其直接映射到实体上,则该实体最终可能会处于无效状态 - 您已经失去了使实体包含数据+逻辑的价值,而这是 DDD 实体的基础。

为了就如何解决这个问题提出建议,我会问 - 您想要实现的操作是什么? DDD 鼓励我们不要考虑 CRUD 操作,而是考虑真实的业务流程,并在我们的实体上对它们进行建模。在本例中,您似乎将订单链接到客户实体。

在应用程序服务中,我有一个类似的方法:

void LinkOrdersToCustomer(CustomerDto dto)
{
    using (var dbTxn = _txnFactory.NewTransaction())
    {
        var customer = _customerRepository.Get(dto.Id);
        foreach (var orderId in dto.OrderIds)
        {
            var order = _orderRepository.Get(orderId);
            customer.LinkToOrder(order);
        }
        dbTxn.Save();
    }
}

在 LinkToOrder 方法中,我将具有执行以下操作的显式逻辑:

  • 检查订单不为空
  • 检查客户的状态是否允许添加订单(他们当前是否处于活动状态?他们的帐户是否已关闭?等)
  • 检查订单是否确实属于该客户(如果 orderId 引用的订单属于另一个客户会发生什么?)
  • 询问订单(通过订单实体上的方法)是否处于可添加到客户的有效状态。

只有这样我才会将其添加到客户订单的集合中。

这样,应用程序“流”和基础设施管理包含在应用程序/服务层中,但真正的业务逻辑包含在域层中 - 在您的实体中。

如果上述要求与您的申请不相关,您可能还有其他要求。如果没有,那么也许没有必要走 DDD 的路——虽然 DDD 有很多东西需要添加,但它的开销通常只有在具有大量复杂业务逻辑的系统中才值得。

这与您提出的问题无关,但我还建议您看一下客户和订单的建模。他们都是独立的吗骨料 http://martinfowler.com/bliki/DDD_Aggregate.html?如果是这样,将 Customer 建模为包含 Order 集合可能会导致出现问题 - 当客户拥有一百万个订单时会发生什么?即使集合是延迟加载的,您也知道在某些时候会尝试加载它,并且您的性能会受到影响。这里有一些关于聚合设计的精彩读物:http://dddcommunity.org/library/vernon_2011/ http://dddcommunity.org/library/vernon_2011/它建议通过 Id 而不是引用来建模引用。在您的情况下,您可能有一个 OrderId 集合,甚至可能有一个全新的实体来表示链接 -CustomerOrderLink它有两个属性 - CustomerId 和 OrderId。那么您的任何实体都不会嵌入集合。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 AutoMapper 从数据库加载实体? 的相关文章

  • 使用遗留代码(使用reinterpret_cast)真的是一种很好的技术吗?

    下面的代码来自一篇关于C 面试问题的帖子here https www toptal com c plus plus interview questions 我从来不知道这种技术 尽管它声称是一种很好的技术 我的问题是 什么情况下需要使用它
  • C++ STL 映射,std::pair 作为键

    这就是我通过地图定义的方式 std map
  • 处理器关联组 C#

    我使用的是 72 核的 Windows Server 2016 我看到有两组处理器 我的 net 应用程序将使用一个或其他组 我需要能够强制我的应用程序使用我选择的组 我看到下面的代码示例 但我无法使其工作 我可能传递了错误的变量 我希望应
  • 没有配置身份验证处理程序来处理该方案

    这是一个非常烦人的问题 我在我的 asp net core 项目上设置 cookie 身份验证 有时会出现此错误 有时不会 没有图案 它只是开始抛出错误 然后突然停止 然后再次开始 例外情况是 InvalidOperationExcepti
  • 使用 C 的另一个结构内的灵活长度结构数组

    你好 我正在尝试使用 C 来实现一个简单的结构 2 个盒子 每个盒子包含不同数量的颗粒 main 中传递的粒子的确切数量 我写了以下代码 typedef struct Particle float x float y float vx fl
  • 如何在 ASP.NET MVC 中处理会话数据

    假设我想存储一个名为language id在会议中 我想我也许可以做如下的事情 public class CountryController Controller WebMethod EnableSession true AcceptVer
  • 二叉树和快速排序?

    我有一个家庭作业 内容如下 别生气 担心 我是not请你帮我做作业 编写一个程序 通过使用二分查找的快速排序方法对一组数字进行排序 树 推荐的实现是使用递归算法 这是什么意思 到目前为止 这是我的解释 正如我在下面解释的那样 我认为两者都有
  • 以编程方式更新 Wifi 网络

    我正在尝试创建一个程序 当某个 wifi 网络在范围内时 该程序会连接到该网络 即使已经连接到另一个 wifi 也是如此 我在用着简单Wifi https github com DigiExam simplewifi 基本上效果很好 除了在
  • 图片框、双击和单击事件

    我有一个奇怪的问题 我有一个图片框双击事件以及单击事件 问题是即使我双击该控件 也会引发单击事件 如果我禁用单击事件 则双击事件正在工作 这个问题已经在这里讨论过 https stackoverflow com questions 1830
  • 在编译输出中添加程序集绑定 (app.config)

    如果我编译应用程序 则会在输出中自动添加程序集绑定 具体的程序集绑定不在app config在 Visual Studio 中但在创建的应用程序配置中 有什么办法可以检查为什么会自动添加程序集绑定吗 选项AutoGenerateBindin
  • Web api 将整数数组传递给操作方法

    我有这个网络 API 方法 HttpGet Route WorkPlanList clientsId date datetime public async Task
  • 如何为二进制格式化程序创建 SerializationBinder,以处理类型从一个程序集和命名空间到另一个程序集和命名空间的移动

    上下文如下 我想通过将代码移动到不同的项目来重构代码 其中一些代码包含可序列化的 DTO 用于 跨多个端点发送和接收数据 如果我移动代码 序列化就会中断 因此它不是 向后兼容我的应用程序的旧版本 这个问题的一个解决方案是 Serializa
  • 将两个垂直滚动条相互绑定

    我在控件中有两个 TextBox 并且它们都有两个 VerticalScrollBar 我想在它们之间绑定 VerticalScrollBars 如果一个向上 第二个也会向上等等 如果可以的话我该怎么做 Thanks 不是真正的绑定 但它有
  • 绑定集合的子集

    我有一个ObservableCollection
  • 大小为 k 的非连续子序列的最大值的最小值

    在开始之前 我希望这个问题不是重复的 我发现了几个类似的问题 但它们似乎都没有描述完全相同的问题 但如果它是重复的 我会很高兴看到一个解决方案 即使它与我的算法不同 我一直在尝试回答这个问题 https stackoverflow com
  • 现代编译器的 C++ 中“memset”功能的状态

    Context 不久前 我偶然发现了 Alexandrescu 在 2001 年发表的 DDJ 文章 http www ddj com cpp 184403799 http www ddj com cpp 184403799 它是关于比较将
  • Qt - 添加超链接到对话框

    有没有办法在 Qt 对话框中添加可点击的超链接 IE 它应该看起来像一个超链接 蓝色文本 当您单击它时 它应该在浏览器中打开该超链接 像这样的东西 Use QLabel setOpenExternalLinks bool 并在标签上设置文本
  • 为什么使用 .AsEnumerable() 而不是转换为 IEnumerable

    扩展方法之一IEnumerable
  • 使用属性和性能

    我正在优化我的代码 我注意到使用属性 甚至自动属性 对执行时间有深远的影响 请参阅下面的示例 Test public void GetterVsField PropertyTest propertyTest new PropertyTest
  • 将“C# 友好类型”名称转换为实际类型:“int” => typeof(int)

    我想得到一个System Type给定一个string指定 原始 类型C 友好名称 基本上与 C 编译器读取 C 源代码时的方式相同 我觉得描述我所追求的最好方式是单元测试的形式 我希望存在一种通用技术 可以使以下所有断言通过 而不是尝试对

随机推荐

  • ArangoDB - 如何在图遍历中执行计算?

    我有一个简单的图表来跟踪我借钱给的人 所以图表看起来像这样 userB owes to amount 200 gt userA userC owes to amount 150 gt userA 等等 假设您需要使用图形遍历来找出每个用户欠
  • 控件不显示是否在后台线程上运行(c# winform)

    我有一个表格 复杂形式在代码中 具有多个控件 需要一些时间来加载 因此 我决定放入一个单独的线程中 以减少初始加载时间 除了等待表单上的标签控件 Form1在代码中 最初不显示 就在 Form1 响起之前的一瞬间 所以我的问题是 为什么标签
  • QMimeData 中的 Python 对象

    我正在基于我的自定义模型实现拖放 QTreeView 一切正常 我的树显示数据 启用了拖放 现在最后一步就在我面前 放置和传输拖动的数据 为此 我需要在模型中实现 mimeTypes mimeData 和 dropMimeData 方法 现
  • 将多个canvas转换为html5中的dataURL

    我想加入多个画布来制作一个图像 那么有没有什么方法可以将多于一张画布隐藏起来toDataURL制作单个图像 创建一个函数 该函数接受多个参数 画布元素 将它们放在一个空白画布上 然后返回新制作的画布的 dataurl var getImad
  • Java 中的逻辑表示法

    绝对基本的 Java 问题 我在 Google 上很难找到 以下是什么意思 7 8 0 这相当于写 7 0 8 0 我写了一个快速的 main 来测试这一点 情况似乎确实如此 我只是想确保我没有遗漏任何东西 Nope is 按位和 http
  • Python 应用程序输出到系统日志服务器

    我正在尝试在谷歌上进行一些搜索 每 5 分钟左右循环一次 当它受到攻击时 我希望它将结果推送到系统日志服务器 我对 python 很陌生 所以请原谅我的无知 我已经搜索了很长时间 但找不到我的问题的答案 我打算添加多个查询来查找不同的结果
  • 逻辑数组 - 在赋值 A(I) = B 中,B 和 I 中的元素数量必须相同

    我有三个矩阵 A B和C 当B大于A时 我想用A使该值饱和 它表示I中的元素数量 即 B gt A 必须与A 中的元素数量 我检查了下面 它们是相同的 gt gt A 5 5 5 5 5 5 5 5 5 gt gt B 2 2 2 2 2
  • 尝试将 Django 国家添加到 Django

    我是 django 的新手 我正在尝试安装 django 国家 但遇到了问题 我安装自http pypi python org pypi django countries 1 0 1 http pypi python org pypi dj
  • 在 asp.net mvc 中使用 jQuery 动态删除表行

    我有一个表 可以动态添加和删除行 model AHBReports Models AdjustmentModel using Html BeginForm table Html EditorFor model gt model Adjust
  • 确定运行 .NET 应用程序的系统要求

    如何确定 NET 应用程序的最低系统要求 我希望能够确定应列出的运行应用程序的最低系统要求 RAM CPU 等 该应用程序是用 C 编写的 并使用 NET 3 5 和 DirectX9 这一切都是关于反复试验 在各种设置中运行它以查看它是否
  • 添加 TwilioController 基类继承后,Microsoft Azure MVC 3 Web 角色未启动

    Azure Web 角色 MVC 3 项目 不会以 Twilio 控制器类启动 我有一个托管在 MS Azure 上的 MVC 3 应用程序 它发布到 Azure Web 角色 没有问题 我添加了 Nuget Twilio 和 Twilio
  • Android 向后代码兼容性

    我正在开发一个应用程序 使用 android hardware Camera parameters getSupportedPictureSizes 这仅适用于 SDK 版本 8 我希望与 SDK 4 兼容 所以我这样做了 if Build
  • 属性错误:“模块”对象没有属性“读者”[重复]

    这个问题在这里已经有答案了 我收到错误 AttributeError 模块 对象没有属性 读者 当我运行下面的代码但我不明白为什么 import csv with open test csv as f q csv reader f 您导入了
  • Pod 处于挂起阶段(错误:FailedScheduling:节点与节点选择器不匹配)

    我的其中一个 pod 有问题 它说它处于待处理状态 如果我描述这个 Pod 我会看到以下内容 Events Type Reason Age From Message Normal NotTriggerScaleUp 1m x58 over
  • 使用 Android Studio 3.1 和 gradle 3.1.0 构建项目时出错

    我对这个项目有一个问题 我尝试在将 Android Studio 更新到 3 1 版本后构建它 我也将 gradle 更新到版本 3 1 0 只是 gradle Sync 工作正常 但尝试编译所有项目显示了这个错误 我已经将构建工具和所有库
  • ejabberd MUC 消息历史记录

    我使用 ejabberd XMPP 服务器作为聊天客户端 它还具有群聊功能 我的问题是 当新用户加入群组房间时 他只能收到来自该房间的前 20 条消息 尽管 History size 设置为 200 目前 在客户端 当新用户加入房间时 存在
  • Java 中“易失性”是什么意思?

    We use volatile在我们的一个项目中 维护由不同线程访问的变量的相同副本 我的问题是是否可以使用volatile with static 编译器没有给出任何错误 但我不明白使用两者的原因 如果没有阅读内存模型规范 我建议您阅读h
  • 如何使用 .net core 的 ILoggerFactory 写入自定义事件源?有没有办法指定来源?

    我正在尝试写入 netcore c 中的自定义事件源 但尚未找到指定 net core 记录器对象的目标源的方法 在这种情况下 我想写入 我的事件日志 而不是应用程序日志 下面的代码成功写入应用程序日志 但我想将其指向 我的事件日志 事件源
  • 使用 BeautifulSoup 查找所有“ul”和“li”元素

    我目前正在 Python 中编写一个爬行脚本 我想将以下 HTML 响应映射到多重列表或字典中 这并不重要 我当前的代码是 from bs4 import BeautifulSoup from urllib request import R
  • 使用 AutoMapper 从数据库加载实体?

    我读过的大部分内容 例如来自作者 http lostechies com jimmybogard 2009 09 18 the case for two way mapping in automapper 指示应使用 AutoMapper