4

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

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

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

4

2 回答 2

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 的消息并检索订单然后取消。

我认为当取消操作比发送消息花费更多的时间时,这很有用。如果硬件资源负担得起,可以添加更多消息处理程序以提高吞吐量。

于 2013-10-17T01:21:41.470 回答
1

仔细考虑之后,我意识到您的问题与此类似:

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

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

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

1 - 数据预加载

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

为此,请参阅[聚合根]

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

2 - 没有预加载的数据迭代

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

3 - 批量数据修改

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

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

于 2013-10-28T21:23:39.233 回答