【问题标题】:'Uncomplete' POCO on client - Can I fill up the collections later?客户端上的“未完成”POCO - 我可以稍后填写收藏吗?
【发布时间】:2011-03-23 08:43:03
【问题描述】:

我有一个使用客户端 -> WCF -> POCO -> EF4 的设置。

假设我有一个包含 A 实体的列表。 A 实体在其他属性中包含大量 B 实体,默认情况下不加载。当客户端完成某个动作时,它可能需要知道 B 实体的列表...

如果我为 A 实体加载 B 实体并将它们附加到集合中,A 实体实际上已更改,我猜在保存实体时它也会将这些“新”B 实体保存到 A 实体?

我可以连接一个GetEntityWithAllDetails 函数,但是我会得到一些我已经拥有的数据,如果还有其他我不想加载的集合,那将是一团糟。

问题可以归结为当我只有部分 POCO 开始并希望避免两次加载数据并且仍然能够依靠 EF4 正确保存实体时,如何在客户端重新完成 POCO ?

【问题讨论】:

    标签: c# .net wcf entity-framework-4 poco


    【解决方案1】:

    这是一项复杂的任务,EF 不会处理它 - 这是您的责任。当您使用分离实体the change tracking is up to you 时。

    您目前的解决方案可能是:

    • 客户端向 WCF 服务发送请求
    • WCF 使用 EF 获取数据、关闭上下文并将 POCO 图或部分图返回给客户端
    • 客户端修改 POCO 图/部分图并将修改后的数据发送回 WCF 服务
    • WCF 创建新的 EF 上下文并保存 POCO 图

    听起来很容易,但事实并非如此。在最后一步中,您必须手动向新上下文解释发生了什么变化。这通常意味着与ObjectStateManager(在ObjectContext API 的情况下)或DbChangeTracker(在DbContext API 的情况下)的大量交互。这也意味着您必须从客户端传递有关更改的信息。

    例如,假设您正在修改Order 实体。 Order 实体依赖于Customer 实体,并且它具有依赖的OrderItem 实体。为了让这个有趣,假设 OrderItems 必须由不同的仓库处理,因此每个仓库只能访问分配给它的项目。

    • 在第一步中,您将从一个仓库请求Order
    • 在第二步中,您将在没有Customer 的情况下退出Order,并使用OrderItems 的supset。
    • 在第三步中,仓库将多个OrderItems 修改为已处理。由于停产产品而删除单个OrderItem,并插入另一个OrderItem以更换停产产品。由于供应不足,一些项目将保持不变。仓库将Order发回服务器。
    • 您将在第四步中做什么?你必须应用一些知识。第一个知识是客户没有发送给客户,因此您无法修改客户关系。在外键关系的情况下,这意味着CustomerId 不能被修改。现在您必须明确指出哪个OrderItem 已更新(= 存在于数据库中),哪个未更改(= 不需要任何操作),哪个已插入(= 必须插入)以及最差的部分已删除(如果您不要从客户端发送一些关于删除的信息,如果不从数据库中重新加载实体图,您就无法知道它)。

    至少您可以高兴的是,EF 不会删除您明确未标记为删除的任何内容。所以与其他仓库相关的订单商品及其与订单的关系不会改变。

    一般有两种处理方法:

    • 首先加载实体图并将更改合并到图中。然后保存附加的(加载的)图表。您只需将加载的实体图与接收的实体图进行比较,并处理所有必需的更新、删除、插入。
    • Use self tracking entities 而不是 POCO,它们是变更集模式的实现,并且能够跟踪客户端上的更改。 STEs have some disadvantages 这使得它们在某些情况下毫无用处。

    还有完全独立的架构方法使用 DTO 而不是直接的 EF POCO,但它会导致与目前相同的复杂性。

    【讨论】:

      【解决方案2】:

      欢迎来到 n 层开发。

      这种情况正是许多架构企业级解决方案使用层间数据传输对象的原因。

      我建议避免从服务(业务)层到客户端的域实体传播。如果你让实体知道它们是否已满载,或者它们当前处于什么层级,那么它们几乎不是“POCO”吗?

      所以你编写了一个服务方法“GetEntityWithAllDetails”。它应该接受一个 GetEntityWithAllDetailsRequest 对象并返回一个 GetEntityWithAllDetailsResponse 对象,其中包含服务调用者期望的任何内容,仅此而已。

      显然,在 DTO 和域对象之间需要进行大量映射 - Automapper(和其他)等库可以提供帮助。

      将域实体传播到客户端还会限制您在延迟或急切加载实体方面的灵活性,并使您不得不处理重新附加/合并实体,这是 EF 的问题,因为它不会重新附加实体图- 你必须手动走图。

      我会试着说得很清楚。将域实体从服务传播到客户端是通向编程地狱的道路,并且很快就会导致对象承担各种责任,而这些责任与它们的目的是一样的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-01
        • 1970-01-01
        • 2012-06-14
        • 2020-11-02
        • 1970-01-01
        • 2016-11-05
        • 2021-08-23
        • 2014-12-28
        相关资源
        最近更新 更多