由于我正在研究一个相对复杂的问题,我想使用领域驱动设计方法来解决它。有问题的是为客户计算月度发票。当前的解决方案是作为一个很难维护的非常长的存储过程实现的。
我想使用面向对象的环境(可能是POCO和实体框架),但我担心性能。当前SP需要大约10分钟才能通过使用set操作生成超过300,000条记录。我认为使用任何ORM都很难实现,因为它将逐个加载实体并以相同的方式发送更新。 (以前的版本在逐个访问记录时需要5个小时。)
您如何为大规模运营创建丰富的模型?
答案 0 :(得分:4)
我在应用富域模型时尽量避免使用大量操作。
某些批次可以替换为事件。例如,我需要每日订单计数报告。
批处理解决方案:
在当天结束时触发的计划任务会从今天下达的订单中收集数据。
或使用活动
PlaceOrderService在下达新订单时发布OrderPlacedEvent。并且eventHandler接收事件并插入到T_ORDER_COUNT_ENTRY
|TODAY |ORDER_ID|
|2012-04-01|123 |
|2012-04-01|124 |
我们可以使用SQL count()来计算每日订单计数报告。
其他一些批次可以并行运行。例如,如果在30分钟内未付款,我的订单应自动取消。
原始批处理解决方案是逐个获取所有满意的订单并调用它们的cancel()。
当前的解决方案是逐个获取所有订单并发送OrderIsOverdue消息。消息处理程序接收包含orderId的消息并检索订单然后取消。
我认为当取消操作比发送消息花费更多时间时,这很有用。如果硬件资源能够负担得起,可以添加更多的消息处理程序来提高吞吐量。
答案 1 :(得分:1)
在考虑之后,我意识到你的问题与这个问题类似:
如何将存储过程重写为域驱动代码?
理论上,它是可能的。您需要做的就是识别并分离存储过程中存在的问题,并以面向对象的方式重写它们。
话虽如此,我预见到为此目标要解决的以下任务:
1 - 数据预加载
存储过程可以使用临时表或表类型的变量,这些表在域驱动的代码中不可用。因此,它归结为预加载实体。这样做是为了让你提前加载所有数据,而不需要在迭代每个实体时加载依赖/子实体 - 你需要将它们全部放在内存中。
为此,请参阅[aggregate roots]
这种方法有一个很大的缺点:内存消耗很高。因此,下一步是。
2 - 没有预加载的数据迭代
存储过程有游标这样的东西。这不会加载数据,而是以有效的方式迭代它。在域驱动的代码中,您实际上无法实现完全相同的效果。有一些接近游标的东西 - [SqlDatReader],但它并不真正在幕后使用SQL游标,所以要小心它。
3 - 批量修改数据
通过在域模型中正确实现[Unit of Work],可以轻松实现此部分。因此,即使您逐个调用实体实例上的修改操作,所有修改也会立即提交到数据库。
我不确定这是否为这个问题增添了一些亮点,但如果您有任何我可以解决的意见,请与我联系。