EDM -> POCO -> WCF (.NET4) 但传输集合导致 IsReadOnly 设置为 TRUE

Posted

技术标签:

【中文标题】EDM -> POCO -> WCF (.NET4) 但传输集合导致 IsReadOnly 设置为 TRUE【英文标题】:EDM -> POCO -> WCF (.NET4) But transferring Collections causes IsReadOnly set to TRUE 【发布时间】:2011-01-29 13:33:57 【问题描述】:

好的,这听起来可能有点“非正统”,但是……使用 VS2010 和新的 POCO t4 实体框架模板 (Walkthrough: POCO Template for the Entity Framework),我可以生成不错的 POCO。然后,我可以在 WCF 服务中使用这些 POCO(作为 DTO),基本上从 EDM 一直到客户端。这家伙在做什么(POCO with EF 4.0 and WCF 4.0),除了一切都是自动生成的。我知道实体和 DTO“应该”不同,但在这种情况下,我正在处理客户端和服务器,并且在模型中自动生成 DTO 有一些真正的优势。

我的问题是,当我传输具有关系的实体时,客户端生成的集合 (ICollection) 具有只读值集,因此我无法操纵该关系。例如,检索现有订单时,我无法将产品添加到 Products 集合客户端...... Products 集合是只读的。

我宁愿做一堆客户端“订单编辑”,然后发回更新的订单,而不是进行数十次服务器往返(例如 AddProductToOrder(product))。我也不想在 Entity 和 DTO 之间有一堆 thunking。所以总而言之,这对我来说看起来不错……除了只读部分。

是否有解决方案,或者这对 SOA 颗粒来说太过分了?

【问题讨论】:

【参考方案1】:

当反序列化发生时,分配给您的 ICollection 的 FixupCollection 将重新创建为一个数组。这就是为什么您的 Products 集合是只读的。

为了修改它,您可以使用“添加服务引用”中的选项(至少在 VS2010 上存在),将 Collection 类型更改为其他类型(Generic.List 或 Generic.Observable)。

但是,如果您使用选项重用现有程序集中存在的类型并引用包含您的实体的程序集,则先前的选项将不会应用于现有类型,并且您的 Products 集合中仍然有 Array。

我使用的一种解决方法(仅当您在客户端重用类型并引用您的实体程序集时)是修改 T4 模板以检查集合在产品获取中是否为只读,如果是则设置 FixupCollection :

if (<#=code.FieldName(navProperty)#>.IsReadOnly)

    var newCollection = new FixupCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>(<#=code.FieldName(navProperty)#>);
    newCollection.CollectionChanged += Fixup<#=navProperty.Name#>;
    <#=code.FieldName(navProperty)#> = newCollection;                   

【讨论】:

【参考方案2】:

“la mouette”解决方案适用于引用的程序集:

我们也有同样的问题,我们注意到在wcf序列化后属性IsReadOnly设置为true(之前属性值为false)。

我们引用了程序集。在“la mouette”提出的解决方法中,使用参数化构造函数,但我们的 POCO 模板没有。

我们已经修改了 tt 创建一个空的构造函数来调用基础构造函数,这样就可以了。

【讨论】:

以上是关于EDM -> POCO -> WCF (.NET4) 但传输集合导致 IsReadOnly 设置为 TRUE的主要内容,如果未能解决你的问题,请参考以下文章

c# WCF 与 POCO DataContract

有啥理由将 POCO 变成 Model 对象?

将 WCF 服务与实体框架 4 和...DTO 一起使用?

我可以告诉 WCF WebAPI 序列化程序忽略嵌套类对象吗?

WCF 关系

在 WCF 数据服务中使用枚举