开发者

WCF DataServices (CTP2): There is a type mismatch between the client and the service

开发者 https://www.devze.com 2023-03-13 05:10 出处:网络
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:

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.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: There is a type mismatch between the client and the service. Type 'Crm.Objects.Segmentation' 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. at System.Data.Services.Client.AtomMaterializer.MaterializeResolvedEntry(AtomEntry entry, Boolean includeLinks) at System.Data.Services.Client.AtomMaterializer.Materialize(AtomEntry entry, Type expectedEntryType, Boolean includeLinks) at System.Data.Services.Client.AtomMaterializer.DirectMaterializePlan(AtomMaterializer materializer, AtomEntry entry, Type expectedEntryType) at System.Data.Services.Client.AtomMaterializerInvoker.DirectMaterializePlan(Object materializer, Object entry, Type expectedEntryType) at System.Data.Services.Client.ProjectionPlan.Run(AtomMaterializer materializer, AtomEntry entry, Type expectedType) at System.Data.Services.Client.AtomMaterializer.Read() at System.Data.Services.Client.MaterializeAtom.MoveNextInternal() at System.Data.Services.Client.MaterializeAtom.MoveNext() at System.Linq.Enumerable.d_b11.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at MangoCrm.Modules.Replication.ReplicaBuilder.GetItems[T](IEnumerable`1 query) at MangoCrm.Modules.Replication.ReplicaBuilder.BeginReplication() at MangoCrm.Modules.Replication.ReplicationWindowControl.b_0() --- End of inner exception stack trace --- at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) at System.Delegate.DynamicInvokeImpl(Object[] args) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args,开发者_如何学编程 Int32 numArgs, Delegate catchHandler)

here is my code:

            var uri = new Uri(webServiceUrl);
            var service = new DataServiceContext(uri);
            MessageBox.Show(service.CreateQuery<Segmentation>("DbSegmentations").ToList().Count.ToString());

Any help?

UPDATE ok now I found out that my WCF responce contains a modified entity object. Here it is:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<entry xml:base="http://localhost:99/Services/CrmDataService.svc/"
       xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
       xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
       xmlns="http://www.w3.org/2005/Atom">
  <id>http://localhost:99/Services/CrmDataService.svc/DbSegmentations(guid'e9854210-85d1-4822-ba70-7e1d3d29cf62')</id>
  <title type="text"></title>
  <updated>2011-06-16T15:07:48Z</updated>
  <author>
    <name />
  </author>
  <link rel="edit" title="Segmentation" href="DbSegmentations(guid'e9854210-85d1-4822-ba70-7e1d3d29cf62')" />
  <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Companies"
        type="application/atom+xml;type=feed"
        title="Companies"
        href="DbSegmentations(guid'e9854210-85d1-4822-ba70-7e1d3d29cf62')/Companies" />
  <category term="Crm.Data.Segmentation" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
  <content type="application/xml">
    <m:properties>
      <d:Id m:type="Edm.Guid">e9854210-85d1-4822-ba70-7e1d3d29cf62</d:Id>
      <d:Name>Promoter</d:Name>
      <d:Description m:null="true" />
      <d:ReplicaInfo m:type="Crm.Data.ReplicaInfo">
        <d:CreateDate m:type="Edm.DateTime">2011-06-09T20:35:22.29</d:CreateDate>
        <d:ModifyDate m:type="Edm.DateTime">2011-06-09T20:35:22.29</d:ModifyDate>
        <d:CreatedById m:type="Edm.Guid">00000000-0000-0000-0000-000000000000</d:CreatedById>
        <d:ModifiedById m:type="Edm.Guid">00000000-0000-0000-0000-000000000000</d:ModifiedById>
        <d:IsDeleted m:type="Edm.Boolean">false</d:IsDeleted>
      </d:ReplicaInfo>
    </m:properties>
  </content>
</entry>

Here is a problem

 <category
 term="Crm.Data.Segmentation"
 scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"
 />

So the question is why my Crm.Objects.Segmentation became Crm.Data.Segmentation? Ho to change it back?

UPDATE2 I think the problem is in my data context. The data context has a namespace Crm.Data. My entities are in Crm.Objects. Then I use 4.0.0 WCF everything is fine, but then I switch to CTP2 my entities get Crm.Data namespace instead of a correct Crm.Objects


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:

  1. Add a [DataServiceKey("Id")] attribute to your entity class. or
  2. Rename your ~Id property so that it ends with ID

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.


I'd say that you're referencing another implementation of the Segmentation class than the service's. Check out the namespace of Segmentation in your CreateQuery<>() call and the namespace of the Segmentation class in your service.


Okay, I think this is a bug of a new WCF CTP2. Then I added back the System.Data.Services 4.0.0 reference I got the correct Namespaces in my data service. But then I use v4.99.2.0 I get the wrong namespace in my ds.


I've had a similar problem, dont know whether or not it will fix yours.

What I had to do was to override the "CreateDataSource" method and turn off proxy creation in the svc.cs file.

Here's the code:

    protected override DataServiceContext CreateDataSource()
    {
        var db = base.CreateDataSource();
        db.Configuration.ProxyCreationEnabled = false;

        return db;
    }


Just came across the same error message and fixed it on my end. Turns out I was mixing up assemblies between my service and client. One was using Microsoft.Data.Services, the other was using System.Data.Services.

0

精彩评论

暂无评论...
验证码 换一张
取 消