WCF DataServices (CTP2): существует несоответствие типов между клиентом и службой - PullRequest
4 голосов
/ 16 июня 2011

Я использую CTP2 WCF Dataservices с Entity Framework 4.1.Теперь, когда я пытаюсь получить любые данные через мой текстовый текст, я получаю следующее исключение:

System.Reflection.TargetInvocationException: Исключение было сгенерировано целью вызова.---> System.InvalidOperationException: существует несоответствие типов между клиентом и службой.Тип 'Crm.Objects.Segmentation' не является типом сущности, но тип в полезной нагрузке ответа представляет тип сущности.Убедитесь, что типы, определенные на клиенте, соответствуют модели данных службы или обновите ссылку на службу на клиенте. в System.Data.Services.Client.AtomMaterializer.MaterializeResolvedEntry (запись AtomEntry, Boolean includeLinks) в системе.Data.Services.Client.AtomMaterializer.Materialize (запись AtomEntry, тип ОжидаемыйEntryType, логический includeLinks) в System.Data.Services.Client.AtomMaterializer.DirectMaterializePlan (запись AtomMaterializer, запись AtomEntry. Тип объекта. At. Atli.AtomMaterializerInvoker.DirectMaterializePlan (Materializer, Object object, Type ОжидаемыйEntryType) в System.Data.Services.Client.ProjectionPlan.Run (материализатор AtomMaterializer, запись AtomEntry, Тип Ожидаемый Тип) в System.Data.Services.Client.AtadMaterSystem.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.Rontlication.Replication.Replication.Replication.Replication.Replication9* _0 () --- Конец внутренней трассировки стека исключений --- в System.RuntimeMethodHandle._InvokeMethodFast (метод IRuntimeMethodInfo, Object target, аргументы Object [], SignatureStruct & sig, MethodAttributes methodAttributes, RuntimeType typeOwner) в System.HuntimeMethod (System.RuntimeMethoF)Метод IRuntimeMethodInfo, объектная цель, аргументы Object [], сигнатура сигнатуры, метод MethodAttributes, методAttributes, RuntimeType typeOwner) в System.Reflection.RuntimeMethodInfo.Invoke (объектный объект, параметры привязки BindingFlags invokeAttr, связыватель связующего, объект [], объектная ссылка на объект CultureSfo)System.Delegate.DynamicInvokeImpl (Object [] args) в System.Windows.Threading.ExceptionWrapper.InternalRealCall (Делегированный обратный вызов, Object args, Int32 numArgs) в MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen (Источник объекта, Метод делегата, Аргументы объекта, Int32 numArgs, Делегат 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 ]

4 голосов
/ 06 февраля 2013

Вы пробовали реализовать делегаты для 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 'не является типом объекта, но тип в полезной нагрузке ответа представляет тип объекта.Убедитесь, что типы, определенные на клиенте, соответствуют модели данных службы или обновите ссылку на службу на клиенте.

Я нашел два исправления, которые сработали для этого:

  1. Добавить[DataServiceKey("Id")] атрибут вашего класса сущности.или
  2. Переименуйте ваше свойство ~ 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.

Надеюсь, это поможет.

0 голосов
/ 18 августа 2013

Просто наткнулся на то же сообщение об ошибке и исправил его на моем конце.Оказывается, я перепутал сборки между моим сервисом и клиентом.Один использовал Microsoft.Data.Services, другой использовал System.Data.Services.

0 голосов
/ 17 июня 2011

Хорошо, я думаю, что это ошибка нового CTP2 WCF.Затем я добавил ссылку System.Data.Services 4.0.0 и получил правильные пространства имен в моей службе данных.Но затем я использую v4.99.2.0, я получаю неправильное пространство имен в моем DS.

0 голосов
/ 16 октября 2011

У меня была похожая проблема, не знаю, исправит ли она вашу проблему.

Мне нужно было переопределить метод "CreateDataSource" и отключить создание прокси в svc.cs.файл.

Вот код:

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

        return db;
    }
0 голосов
/ 16 июня 2011

Я бы сказал, что вы ссылаетесь на другую реализацию класса Segmentation, отличную от службы. Проверьте пространство имен Segmentation в вашем вызове CreateQuery<>() и пространство имен класса Segmentation в вашем сервисе.

...