如何将富域与大规模操作一起使用



由于我正在研究一个相对复杂的问题,我想使用领域驱动设计方法来解决这个问题。有问题的问题是为客户计算月度发票。当前解决方案是作为非常长的存储过程实现的,难以维护。

我想使用面向对象的环境(可能是POCO和实体框架),但我担心性能。当前 SP 使用集合操作生成超过 300,000 条记录大约需要 10 分钟。我认为这很难用任何ORM实现,因为它会一个接一个地加载实体并以相同的方式发送更新。(以前的版本在逐个访问记录时需要 5 个小时。

如何为大规模运营创建丰富的模型?

在应用富域模型时,我尽可能避免使用大量操作。

某些批次可以替换为事件。例如,我需要每日订单盘点报告。

批处理解决方案:

在一天结束时触发的计划任务从今天下达的订单中收集数据。

或使用事件

PlaceOrderService 会在下新订单时发布 OrderPlacedEvent。事件处理程序接收事件并插入到T_ORDER_COUNT_ENTRY

|TODAY     |ORDER_ID|
|2012-04-01|123     |
|2012-04-01|124     |

我们可以使用 SQL count() 来计算每日订单计数报告。

其他一些批处理可以并行运行。例如,如果在 30 分钟内未付款,我的订单应自动取消。

原始批处理解决方案是逐个获取所有满足的订单并调用它们的 cancel()。

当前的解决方案是逐个获取所有满足的订单,并发送OrderIsOverdue消息。消息处理程序接收包含 orderId 的消息,并检索订单,然后取消。

我认为当取消操作花费的时间远远超过发送消息时,这很有用。如果硬件资源可以承受,可以添加更多的消息处理程序来改进 虽然。

经过思考,我意识到你的问题与此类似:

如何将存储过程重写为域驱动的代码?

从理论上讲,这是可能的。您需要做的就是识别和分离存储过程中存在的问题,并以面向对象的方式重写它们。

话虽如此,我预计要为此目标解决以下类型的任务:

1 - 数据预加载

存储过程可以使用临时表或表类型的变量,这些在域驱动的代码中不可用。因此,它归结为预加载实体。这样做是为了提前加载所有数据,而无需稍后在迭代每个实体时加载依赖/子实体 - 您需要将它们全部放在内存中。

为此,请参阅 [聚合根]

这种方法有一个很大的缺点:内存消耗高。因此,下面的下一步。

2 - 无需预加载的数据迭代

存储过程具有游标之类的东西。这不会加载数据,而是以有效的方式迭代数据。但是,在域驱动的代码中,您无法真正实现完全相同的效果。有一些接近游标的东西 - [SqlDatReader],但它并没有真正在幕后使用 SQL 游标,所以要小心它。

3 - 批量数据修改

通过在域模型中正确实现[工作单元],可以轻松实现这部分。因此,即使您逐个调用实体实例上的修改操作,所有修改也会立即提交到数据库。

我不确定这是否为问题增添了一些线索,但如果您有任何我可以解决的意见,请告诉我。

最新更新