WCF DataServices(CTP2):客户端和服务之间存在类型不匹配

本文关键字:之间 服务 存在 类型 不匹配 客户端 DataServices CTP2 WCF | 更新日期: 2023-09-27 17:59:13

我使用的是带有实体框架4.1的WCF数据服务CTP2。现在,我正试图通过我的数据上下文获取任何数据,我得到了这个异常:

System.Reflection.TargetInvocationException:已由引发异常调用的目标。--->System.InvalidOperationException:在客户端和服务。类型"Crm.Objects.Segmentation"不是实体类型,但响应有效载荷表示一个实体类型请确保已定义类型关于客户端匹配的数据模型服务,或更新服务客户的参考在System.Data.Services.Client.AtomMaterializer.MaterializeResolvedEntry(AtomEntry条目,布尔includeLinks)System.Data.Services.Client.AtomMaterializer.Materialize(AtomEntryentry,预期类型EntryType,布尔值includeLinks)System.Data.Services.Client.AtomMaterializer.DirectMaterializePlan(AtomMaterializer物化器,AtomEntry条目,类型expectedEntryType)System.Data.Services.Client.AtomMaterializerInvoker.DirectMaterializePlan(对象物化器,对象条目,类型expectedEntryType)System.Data.Services.Client.ProjectionPlan.Run(AtomMaterializer物化器,AtomEntry条目,类型expectedType)System.Data.Services.Client.AtomMaterializer.Read()在System.Data.Services.Client.MaterializeAtom.MoveNextInternal()在System.Data.Services.Client.MaterializeAtom.MoveNext()在System.Linq.Enumerable.d_b1 1.MoveNext() at System.Collections.Generic.List 1..ctor(IEnumerable 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable 1来源)MangoCrm.Modules.ReplicaBuilder.GetItems[T](IEnumerable`1查询)MangoCrm.Modules.Replication。ReplicaBuilder.BeginReplication()在MangoCrm.Modules.ReplicationWindowControl.b_0()---内部异常堆栈跟踪结束---在System.RuntimeMethodHandle_InvokeMethodFast(IRuntimeMethodInfo方法,Object target,Object[]自变量,SignatureStruct&sig,MethodAttributes MethodAttributes,RuntimeType typeOwner)System.RuntimeMethodHandle.IInvokeMethodFast(IRuntimeMethodInfo方法,Object target,Object[]arguments,Signature sig,MethodAttributes MethodAttributes,RuntimeType typeOwner)System.Reflection.RuntimeMethodInfo.IInvoke(对象obj,BindingFlags invokeAttr,Binderbinder,Object[]参数,CultureInfo区域性,布尔skipVisibilityChecks)System.Delegate.DynamicInvokeImpl(Object[]args)System.Windows.Threading.ExceptionWrapper.InternalRealCall(委托callback,Object args,Int32 numArgs)在MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(对象source,Delegate方法,Object参数,Int32 numArgs,Delegate catchHandler)

这是我的代码:

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

有什么帮助吗?

更新好的,现在我发现我的WCF响应包含一个修改过的实体对象。这是:

<?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>

出现问题

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

所以问题是为什么我的Crm.Objects.Segmentation变成了Crm.Data.Segmentation?怎么把它改回来?

更新2我认为问题出在我的数据环境中。数据上下文有一个名称空间Crm.data。我的实体在Crm.Objects中。然后我使用4.0.0 WCF,一切都很好,但后来我切换到CTP2,我的实体得到了Crm.data名称空间,而不是正确的Crm.Objects

WCF DataServices(CTP2):客户端和服务之间存在类型不匹配

你尝试为DataServiceContext.ResolveNameDataServiceContext.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"不是实体类型,但响应负载中的类型表示实体类型。请确保客户端上定义的类型与服务的数据模型匹配,或者更新客户端上的服务引用。

我发现了两个适用于此的修复程序:

  1. [DataServiceKey("Id")]属性添加到实体类中。或
  2. 重命名~Id属性,使其以ID结尾

我通过查看反编译的IL(这是针对WCF Data Services 5.2.0的)找到了#2。在查看了ClientEdmModelClientTypeUtil之后,我在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;
}

在WCF数据服务的客户端使用POCO时,name1.EndsWith("ID"是关键。

希望能有所帮助。

我认为您引用的是Segmentation类的另一个实现,而不是服务的实现。检查CreateQuery<>()调用中Segmentation的命名空间和服务中Segmentation类的命名空间。

好吧,我认为这是一个新的WCF CTP2的错误。然后我添加回系统。数据Services 4.0.0引用我在数据服务中获得了正确的命名空间。但后来我使用了v4.99.2.0,我的ds中出现了错误的命名空间。

我也遇到过类似的问题,不知道它是否能修复你的问题。

我所要做的是覆盖"CreateDataSource"方法并关闭svc.cs文件中的代理创建。

这是代码:

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

刚刚遇到了相同的错误消息,并在我这边修复了它。原来我把服务和客户端之间的程序集搞混了。其中一个是使用微软。数据服务,另一个正在使用系统。数据服务。