您是否尝试过实施代表DataServiceContext.ResolveName
and DataServiceContext.ResolveType
?这 2 个委托(如果提供)可用于修复 odata 命名空间 + 名称以及在客户端上序列化和反序列化的类型之间的映射。
这是一个简单的例子:
internal class CustomDataServiceContext : DataServiceContext
{
public CustomDataServiceContext(Uri serviceRoot)
: base(serviceRoot, DataServiceProtocolVersion.V3)
{
this.ResolveName = ResolveNameFromType;
this.ResolveType = ResolveTypeFromName;
}
protected string ResolveNameFromType(Type clientType)
{
if (clientType.Namespace.Equals("ODataClient.MSProducts", StringComparison.Ordinal))
{
return string.Concat("ODataService.Models.", clientType.Name);
}
return clientType.FullName;
}
protected Type ResolveTypeFromName(string typeName)
{
if (typeName.StartsWith("ODataService.Models", StringComparison.Ordinal))
{
return this.GetType().Assembly.GetType(string.Concat("ODataClient.MSProducts", typeName.Substring(19)), false);
}
return null;
}
}
为了使我的实体类在 WCF 数据服务客户端中工作,我必须做这样的事情(但我使其灵活而不是硬编码);
但即使这样做之后,我还是遇到了这个错误:
System.InvalidOperationException:客户端和服务之间存在类型不匹配。 “Type WorkItem”不是实体类型,但响应负载中的类型表示实体类型。请确保客户端上定义的类型与服务的数据模型匹配,或更新客户端上的服务引用。
我发现了两个对此有效的修复:
- Add a
[DataServiceKey("Id")]
属性到您的实体类。
或者
- 重命名您的 ~Id 属性,使其结尾为
ID
我通过困难的方式找到了 #2 - 查看反编译的 IL(这是针对 WCF Data Services 5.2.0 的)。审核后ClientEdmModel
and ClientTypeUtil
,我在中遇到了这个方法ClientTypeUtil
:
private static ClientTypeUtil.KeyKind IsKeyProperty(PropertyInfo propertyInfo, DataServiceKeyAttribute dataServiceKeyAttribute)
{
string name1 = propertyInfo.Name;
ClientTypeUtil.KeyKind keyKind = ClientTypeUtil.KeyKind.NotKey;
if (dataServiceKeyAttribute != null && dataServiceKeyAttribute.KeyNames.Contains(name1))
keyKind = ClientTypeUtil.KeyKind.AttributedKey;
else if (name1.EndsWith("ID", StringComparison.Ordinal))
{
string name2 = propertyInfo.DeclaringType.Name;
if (name1.Length == name2.Length + 2 && name1.StartsWith(name2, StringComparison.Ordinal))
keyKind = ClientTypeUtil.KeyKind.TypeNameId;
else if (2 == name1.Length)
keyKind = ClientTypeUtil.KeyKind.Id;
}
return keyKind;
}
就是那个name1.EndsWith("ID"
这是在 WCF 数据服务客户端使用 POCO 时的关键。
希望有帮助。