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

时间:2011-06-16 11:42:34

标签: c# wcf c#-4.0 entity-framework-4.1 wcf-data-services

我正在使用带有Entity Framework 4.1的WCF Dataservices CTP2。现在我正试图通过我的datacontext获取任何数据我得到了这个例外:

  

System.Reflection.TargetInvocationException:   例外已被抛出   调用的目标。 --->   的 System.InvalidOperationException:   这之间存在类型不匹配   客户和服务。类型   'Crm.Objects.Segmentation'不是   实体类型,但是类型   响应有效负载表示实体   类型。请确保定义类型   在客户端上匹配数据模型   服务,或更新服务   客户参考。 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条目,类型   expectedEntryType)at   System.Data.Services.Client.AtomMaterializerInvoker.DirectMaterializePlan(对象   materializer,对象条目,类型   expectedEntryType)at   System.Data.Services.Client.ProjectionPlan.Run(AtomMaterializer   materializer,AtomEntry条目,类型   expectedType)at   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.Replication.ReplicaBuilder.GetItems [T](IEnumerable`1   查询)   MangoCrm.Modules.Replication.ReplicaBuilder.BeginReplication()   在   MangoCrm.Modules.Replication.ReplicationWindowControl.b _0()   ---内部异常堆栈跟踪结束---在System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo)   方法,对象目标,对象[]   参数,SignatureStruct& SIG,   MethodAttributes methodAttributes,   RuntimeType typeOwner)at   System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo   方法,对象目标,对象[]   参数,签名信号,   MethodAttributes methodAttributes,   RuntimeType typeOwner)at   System.Reflection.RuntimeMethodInfo.Invoke(对象   obj,BindingFlags invokeAttr,Binder   binder,Object []参数,   CultureInfo文化,布尔   skipVisibilityChecks)at   System.Delegate.DynamicInvokeImpl(对象[]   args)at   System.Windows.Threading.ExceptionWrapper.InternalRealCall(代表   callback,Object args,Int32 numArgs)   在   MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(对象   source,Delegate方法,Object args,   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的原因?何要改回来?

UPDATE2 我认为问题出在我的数据环境中。数据上下文具有名称空间Crm.Data。我的实体在Crm.Objects中。然后我使用4.0.0 WCF一切都很好,但后来切换到CTP2我的实体获取Crm.Data命名空间而不是正确的Crm.Objects

5 个答案:

答案 0 :(得分:4)

您是否尝试为DataServiceContext.ResolveNameDataServiceContext.ResolveType实施代理?这两个代理(如果提供)可用于修复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'不是实体类型,但响应有效内容中的类型表示实体类型。请确保客户端上定义的类型与服务的数据模型匹配,或者更新客户端上的服务引用。

我找到了两个适用于此的修复:

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

    我很难找到#2 - 看看反编译的IL(这是针对WCF数据服务5.2.0)。在审核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"是关键。

    希望有所帮助。

答案 1 :(得分:0)

我会说你引用的是Segmentation类的另一个实现,而不是服务的实现。查看Segmentation调用中CreateQuery<>()的命名空间以及服务中Segmentation类的命名空间。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我遇到了类似的问题,不知道它是否能解决你的问题。

我必须做的是覆盖“CreateDataSource”方法并关闭svc.cs文件中的代理创建。

以下是代码:

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

        return db;
    }

答案 4 :(得分:0)

刚刚遇到相同的错误消息并将其修复到我的最后。原来我在服务和客户端之间混合了程序集。一个是使用Microsoft.Data.Services,另一个是使用System.Data.Services。