I\'m using WCF Dataservices CTP2 with Entity Framework 4.1. Now then I\'m trying to get any data through my datacontext I get this exception:
System.R
Did you try implementing delegates for DataServiceContext.ResolveName
and DataServiceContext.ResolveType
? Those 2 delegates, if provided, can be used to fixup the mapping between odata namespaces + names, and the types that are serialized and deserialized on the client.
Here is a simple example:
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;
}
}
I had to do something like this (but I made it flexible instead of hard-coded) in order to make my entity classes work in the WCF Data Services client;
But even after doing this, I had this error:
System.InvalidOperationException : There is a type mismatch between the client and the service. Type WorkItem' is not an entity type, but the type in the response payload represents an entity type. Please ensure that types defined on the client match the data model of the service, or update the service reference on the client.
I found two fixes that worked for this:
[DataServiceKey("Id")]
attribute to your entity class.
orID
I figured out #2 the hard way - looking at the decompiled IL (this is for WCF Data Services 5.2.0). After reviewing ClientEdmModel
and ClientTypeUtil
, I came across this method in 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;
}
It's that name1.EndsWith("ID"
that is the key when using your POCOs on the client side of WCF Data Services.
Hope that helps.