我在使用WCF和Entity Framework 4.1 POCO对象时遇到问题(使用T4模板生成)。我的基本问题是,当从客户端向服务发送POCO对象时,WCF将ICollection类型的成员变量反序列化为固定大小的数组。
在客户端,我可以告诉visual studio使用IList而不是T [] - 但我在服务器端看不到这样的选项。
这会导致几个问题无法解决,例如将这些对象持久化回数据库。
有没有办法告诉WCF将ICollection(或任何数组)反序列化的对象类型是什么?
答案 0 :(得分:5)
我很惊讶更多的人没有遇到过这个问题,因为当你试图在WCF上使用EF T4生成的POCO对象时,你会遇到这个问题。具体来说,我得到的错误就是:
异常:“无法在实体类型Datalayer.Customers上设置字段/属性订单。有关详细信息,请参阅InnerException。”
InnerException:“无法将项目添加到'Datalayer.Order []'类型的固定大小数组中。”
无论如何,我能够提出的唯一解决方案是你提到的解决方案,即修改T4模板以使用HashSet而不是ICollection。不会让我觉得最干净,但似乎有效。
答案 1 :(得分:1)
我使用的是Entity Framework 6,我可以通过在T4模板中进行以下更改来解决此问题。
我更改了以下行,在该行中创建导航属性以使用List而不是
中的集合navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
到
navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("List<" + endType + ">") : endType,
然后我更改了在构造函数中设置navigation属性的代码,通过添加对.ToList()的调用将默认的hashset转换为列表。这一行
this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
已更改为
this.<#=code.Escape(navigationProperty)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>().ToList();
HashSet&lt;&gt; .ToList()方法是一个扩展,因此为了使该扩展方法可用,我通过修改UsingDirectives方法添加了一个使用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)
: "";
}