Вы пробовали реализовать делегаты для DataServiceContext.ResolveName
и 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: существует несоответствие типов между клиентом и службой.Тип WorkItem 'не является типом объекта, но тип в полезной нагрузке ответа представляет тип объекта.Убедитесь, что типы, определенные на клиенте, соответствуют модели данных службы или обновите ссылку на службу на клиенте.
Я нашел два исправления, которые сработали для этого:
- Добавить
[DataServiceKey("Id")]
атрибут вашего класса сущности.или - Переименуйте ваше свойство ~ Id так, чтобы оно заканчивалось на
ID
Я понял сложный путь № 2 - глядя на декомпилированный IL (это для WCF Data Services5.2.0).Изучив ClientEdmModel
и 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"
является ключом при использовании ваших POCO на стороне клиента служб данных WCF.
Надеюсь, это поможет.