5

我在使用 WCF 和 Entity Framework 4.1 POCO 对象(使用 T4 模板生成)时遇到问题。我的基本问题是,当从我的客户端向服务发送 POCO 对象时,WCF 将 ICollection 类型的成员变量反序列化为固定大小的数组。

在客户端,我可以告诉 Visual Studio 使用 IList 而不是 T[] - 但我在服务器端看不到任何这样的选项。

这会导致一些问题没有尽头,例如将这些对象持久化回数据库。

有没有办法告诉 WCF 将 ICollection(或任何数组)反序列化为什么对象类型?

4

2 回答 2

5

我很惊讶更多的人没有遇到这个问题,因为当您尝试通过 WCF 使用 EF T4 生成的 POCO 对象时,它会让您大吃一惊。具体来说,我得到的错误是这样的:

异常:“无法在实体类型 Datalayer.Customers 上设置字段/属性订单。有关详细信息,请参阅 InnerException。”

InnerException:“无法将项目添加到 'Datalayer.Order[]' 类型的固定大小数组中。”

无论如何,我能想出的唯一解决方案就是您提到的那个,即修改 T4 模板以使用 HashSet 而不是 ICollection。没有让我觉得最干净,但它似乎有效。

于 2012-06-01T08:33:50.733 回答
1

我正在使用 Entity Framework 6,我能够通过在我的 T4 模板中进行以下更改来解决此问题。

我更改了以下行,它在其中创建导航属性以使用 List 而不是来自的集合

navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,

navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("List<" + endType + ">") : endType,

然后我更改了在构造函数中设置导航属性的代码,通过添加对 .ToList() 的调用将默认哈希集转换为列表。这条线

this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();

改为

this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>().ToList();

HashSet<>.ToList() 方法是一个扩展,因此为了使该扩展方法可用,我通过修改 UsingDirectives 方法添加了 using System.Linq 语句:

    public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
    return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
        ? string.Format(
            CultureInfo.InvariantCulture,
            "{0}using System;{1}" + Environment.NewLine +
            "{0}using System.Linq;" + 
            "{2}",
            inHeader ? Environment.NewLine : "",
            includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
            inHeader ? "" : Environment.NewLine,
            Environment.NewLine)
        : "";
}
于 2014-12-10T21:14:57.320 回答