【问题标题】:Entity Framework and DTO实体框架和 DTO
【发布时间】:2011-08-20 02:36:30
【问题描述】:

我打算使用 EF (POCO) 生成的实体向客户端发送数据而不是创建 DTO?这是一个好习惯吗?基本上,我的 EDMX 文件在我的 DAL 层上。 所以 UI 可以直接访问我的 DAL。谢谢。

【问题讨论】:

    标签: c# dto


    【解决方案1】:

    这取决于客户端与您的对象域的距离。如果它是您的客户,那么可能 - 实际上这就是 ADO.NET 数据服务(等)的工作方式 - 直接公开您的模型。

    但是,如果客户是其他任何东西,我建议使用专用的 DTO。事实上,我还是建议这样做;p 否则,它会变得有些复杂:

    • 控制序列化细节(什么成员?什么名字?版本化时会发生什么?)
    • 处理关系属性(它一个Orders 成员...但这是延迟加载吗?我们想要那个吗?)
    • 将传入对象(用于更新等)合并回模型中
    • 在反序列化期间抑制您在 setter 等中添加的任何逻辑
    • 如果您在基于树的序列化程序(如 DataContractSerializer)中获得同一对象的 2 个单独副本,则处理身份管理

    在大多数情况下,拥有一个单独的 DTO 会使这些问题中的大部分消失

    【讨论】:

    • 我只在需要像 WCF 那样序列化的进程中使用 DTO 是否有意义,而在像绑定到网格这样的简单数据获取中我将使用 EF 的实体?
    • 您的意思是当 EF 实体客户有订单时,即使我并不真正需要订单,它也会被加载?我认为在您调用 customer.Orders.Load() 之前它不会加载?
    • @dotnetlinc 用于本地使用,EF 对象通常很好 - 实际上我专注于 WCF(等)的使用。关于订单问题:我的观点主要是完全消除该问题,以及您对订单传入数据所做的操作的复杂性。通过在 DTO 和域对象之间进行清晰的分离,您可以获得更清晰的代码,并且由于传入/传出数据 (DTO) 和实际可信数据(域模型)的模糊性而产生的陷阱要少得多
    • 谢谢马克!我想我会尝试这种方法,在简单的绑定中使用 Domain.Customer(EFs 实体),然后当我必须公开/序列化实体时,只需创建一个 DTO.Customer ... =)
    【解决方案2】:

    基本上,我认为将 DAL 对象发送到您的界面不是一个好主意,所以我会使用 DTO。为了尽量减少这样做的工作量,我会看一下DTO generator,以生成 DTO 代码,它可以让您从 DAL 对象转换为 DTO,反之亦然。

    编辑:抱歉,没有看到您正在使用 POCO。看看这个SO post

    【讨论】:

    【解决方案3】:

    首先,我相信你不能在你的服务中使用实体框架生成的实体作为返回类型,至少在 WCF 服务中是这样。

    但是,为什么要在整个应用程序中使用实体?如果您有一个具有客户端-服务器结构的通用架构,那么您的客户端将不需要 EntityObject 拥有的所有信息,例如包含它的 ObjectContext、它的状态以及您的客户端不仅需要的许多其他信息不会使用,但更重要的是:不必知道。

    在这种情况下,您应该使用 DTO 模式,或者您认为更好的其他设计模式,将服务器端与客户端分离。我相信 DTO 模式是最广泛使用和推荐的。 如果您使用的是实体框架,您可以转到http://entitiestodtos.codeplex.com,它是我发布的 Visual Studio 插件,它是免费和开源的。它从您的实体框架数据模型 (EDMX) 生成您的 DTO。

    问候, 法比安·费尔南德斯

    【讨论】:

      【解决方案4】:

      DTO 是一种很好的做法,可以最大限度地减少通过网络传输的数据量,只包含相关字段。这是其他好处之一。 Checkout Automapper 和 ProjectTo 方法可以自动将 DAL 转换为 DTO,反之亦然。引擎盖下的 ProjectTo 将仅选择已配置映射中包含的列。

      https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions

      【讨论】:

        【解决方案5】:

        使用EntityFramework代码先TT如“EntityFramework Reverse POCO Generator” (https://marketplace.visualstudio.com/items?itemName=SimonHughes.EntityFrameworkReversePOCOGenerator) 在单独的业务实体模型库中生成与数据库表模式关联的业务模型。可以修改 TT 以包含专门针对 WCF 实体的自定义属性(例如 DataMember、Serializable)。

        这种方式可以兼具 DTO 和 EF POCO 的好处。它可以轻松地保持业务模型实体和数据库表之间的一致性。

        原因是,在大多数情况下,任何时候修改数据库表结构,开发者也需要一致的业务模型结构(这里是DTO)。维护映射器还有其他工作。

        如果数据库访问层模型(这里是EF POCO)与DTO模型松耦合。开发人员将很难检测到编译时无法显示的潜在错误,专门用于维护现有的企业级应用程序。

        如果我们有业务模型实体所需的其他自定义属性,我们可以添加具有自定义属性的部分类。

        我们仍然可以在需要时使用映射器将 EF POCO 实体转换为 DTO 实体。但我的观点是,与直接将数据绑定到 EF POCO 模型相比,尽量减少使用仅做重复工作的映射器的滥用。

        由于我们可以在单独的业务模型库中生成 EF POCO 实体,因此 DTO 实体能够与它们保持在同一个业务模型库中。因此,开发人员可以更灵活地决定如何使用它们。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-19
          • 2011-08-19
          • 1970-01-01
          • 2011-10-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-16
          相关资源
          最近更新 更多