【问题标题】:Is this a proper use of DTO?这是正确使用 DTO 吗?
【发布时间】:2011-09-12 17:10:48
【问题描述】:

我正在编写一个控制台应用程序,它可以从存储过程记录集中进行大量数据检索。对于我正在使用的每种记录集类型,我都有一个使用 EF 和自定义复杂类型来检索数据的存储库:

public interface IBalanceSheetRepository
{
    IEnumerable<BalanceSheetRecordDTO> GetBalanceSheetRecords();
}

public class BalanceSheetRepository : IBalanceSheetRepository
{
    DBContext _context;

    ...

    public IEnumerable<BalanceSheetRecordDTO> GetBalanceSheetRecords()
    {
        ObjectResult<BalanceSheetRecord> results = _context.GetBalanceSheet();
        return results.Select(CreateBalanceSheetDTOFromDAO);
    }

    private static BalanceSheetRecordDTO CreateBalanceSheetDTOFromDAO(BalanceSheetRecord dao)
    {
        return new BalanceSheetRecordDTO { ... };
    }
}

这里,BalanceSheetRecord 是我在设计器中创建的复杂数据类型。我创建了一个 DTO 以避免耦合,因为 BLL 不应该知道 BalanceSheetRecord 类型。

这是我的问题:由于 DTO 类型用于存储库接口的方法签名中,并且由于我的 BLL 最终将使用存储库并返回 DTO 的集合,因此这似乎是一个横切关注点。因此,我将 DTO 与 repo 接口一起生活在一个单独的“基础设施”程序集中。这是我想要实现的目标的好做法,还是我在某个地方走错了路?

另外:在我的存储库中更新数据上下文是不好的做法吗?当两个组件都属于 DAL 时,一定数量的耦合是否可以?我想使用 DI,但它似乎更有用,例如将 repo 的 DBContext 实现换成TestBalanceSheetRepository。

【问题讨论】:

    标签: c# .net entity-framework domain-driven-design dto


    【解决方案1】:

    我更喜欢从我的存储库中返回实际实体。这样,当您需要在服务层中协调不同实体之间的复杂交互时,就无需来回转换为 DTO。然后,服务层在向应用层返回数据时将实体投影到 DTO 中。

    我知道有些纯粹主义者说层之间的所有交互都应该使用 DTO 完成,但我认为这不切实际。无论如何,服务层最终都会与实体耦合,所以这不像您要添加耦合。

    它还限制了 DTO 到服务层的实体的投影/展平。这对我来说是一个加分项,因为这些活动增加了复杂性并降低了性能。

    您的数据上下文是您的工作单元。 “每个存储库一个工作单元”的想法是一种反模式。工作单元应由服务层限定范围,它可能涉及来自 1-many 存储库的 1-many 实体。如果每个存储库都有不同的工作单元,您将无法让服务层调用轻松维护一致的事务。

    【讨论】:

    • 同意。存储库应返回域对象。在系统之间的边界,如 Web 服务,最好返回 DTO,这样外部系统就不会与您的域模型紧密耦合。
    • @Carl Raymond:是的,但我永远不会直接通过 Web 服务公开存储库。我总是会在它上面放置一个服务层,它可以进行 DTO 的投影/展平和编排。直接公开存储库会给您带来非常“CRUDy”的服务调用和过于繁琐的应用程序,业务逻辑分散在客户端中。
    • 这就是我的意思。我想当我说“可以更好”时,我的意思是“几乎总是更好,除非你有一些非常特殊的情况”。我没有考虑健谈,但这是另一个好点。 Web 服务 API 的结构与存储库不同,以最大限度地减少完成任务所需的网络流量。
    • 作为一种节省编写 DTO 时间的方法,您可以使用EntitiesToDTOs,它会自动从您的 EDMX 生成 DTO 和汇编程序。
    • 这实际上是我不建议的。 DTO 应该尽可能地针对具体用途,并且只包含给定用途所需的内容。如果您使用生成器仅使用实体中的所有字段生成 DTO,然后在许多服务调用中重复使用相同的 DTO,那么您做错了,IMO。
    猜你喜欢
    • 2021-11-20
    • 2011-02-25
    • 1970-01-01
    • 2018-08-13
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多