0

我必须使用 CartLine 和其他一些信息创建一个复杂的“读取模型”(购物车)。目前我有一个基于许多其他对象(Cart、Operation...)的 ViewModel,构建此对象的逻辑在 Respository 和 Controller(不在 Aggregate 中)中调度,我想重构这段代码,使用存储库直接返回“读取模型”(带有格式化文本,价格......)。

我只被允许在 Dapper 中使用存储过程(客户的策略)。我正在寻找一种更好的方法来创建这个读取模型:

1.调用现有存储过程,将存储过程结果映射到DTO上,然后再次将结果映射到我的读取模型上

public class Cart
{
    public Cart(CartDb cartDb, IEnumerable<CartDetailDb> cartDetailsDb, 
                                                      OperationDB operationDb)
    {
        //Code
    }
}

-> 有两个层次的对象,我觉得很乱

2.创建将直接映射到我的读取模型的存储过程(以避免 DTO)

-> 我不喜欢这种方法,因为我最终可能会在存储过程中添加一些逻辑

3.使用视图模型

其他建议?

4

1 回答 1

1

如果我理解正确,您的该实体的数据模型与您的该实体的域模型并不完全一致Read。您还希望您的存储库层直接返回您的域模型版本,Read而不需要一些中间 DTO 层。

在我看来,选项#1最有意义。因为您的数据模型和域模型之间存在阻抗不匹配,所以在某处需要映射逻辑来在两个模型之间转换数据。这个逻辑最合适的地方是在你的存储层内部,因为这个层的全部目的是在域和它们的持久性之间映射对象。

这并不意味着您需要创建一个 DTO 层来从您的存储过程进行映射,然后您转身并重新映射到域对象。您可以简单地直接对数据访问层返回的结果集执行翻译逻辑,并一步将其转换为域对象。

在数据访问的情况下,对 DTO 的需求很大程度上取决于您用于数据访问的技术。例如,如果您使用的是 ADO.net 库(SqlCommandSqlConnection等),则可能不需要 DTO。但是,如果您使用的是 Entity Framework 或 NHibernate 之类的 ORM,那么将这些工具生成的对象严格用作 DTO 并映射到完整的域对象可能是有意义的。当然,由于这些对象是为您生成的,因此几乎消除了拥有 DTO 层的任何维护问题。

这也不意味着您需要将转换逻辑放在存储过程中,以使数据层返回与您的域模型完全匹配的结果集。正如您自己所说,我会不惜一切代价避免这种情况,这会将域逻辑放入您的数据库中。

最后,您提到域对象由“格式化文本”组成,例如价格。我要指出,大多数时候文本格式实际上是 UI 层的一部分,而不是您的域模型。这意味着如果您的模型上有一个属性,例如Price,它应该表示为DoubleorDecimal而不是String格式化为货币。换句话说,该值应该是5.00而不是"$5.00"

为了处理像这样的格式翻译,用ViewModel你提到的类似的包装你的域对象是合适的,以处理从域到 UI 层的翻译。在此类情况下使用严格的分离关注点有助于创建更健壮且更易于维护的系统。

于 2012-09-18T17:20:01.850 回答