消费OData服务时出现错误——客户端和服务之间存在类型不匹配

本文关键字:服务 之间 类型 不匹配 客户端 存在 错误 OData 消费 | 更新日期: 2023-09-27 18:02:23

我正在尝试使用OData v4服务。该服务具有以下相关元数据:

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
    <edmx:DataServices>
        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Some.Name.Space">
            <EntityType Name="StatisticalProgram">
                <Key>
                    <PropertyRef Name="Id"/>
                </Key>
                <Property Name="Name" Type="Edm.String"/>
                <Property Name="ShortName" Type="Edm.String"/>
                <Property Name="Deployed" Type="Edm.Boolean" Nullable="false"/>
                <Property Name="CreatedBy" Type="Edm.String"/>
                <Property Name="CreatedDate" Type="Edm.DateTimeOffset" Nullable="false"/>
                <Property Name="UpdateBy" Type="Edm.String"/>
                <Property Name="UpdatedDate" Type="Edm.DateTimeOffset"/>
                <Property Name="Id" Type="Edm.Guid" Nullable="false"/>
            </EntityType>
       // Other....

我想映射到这个模型:

[DataServiceKey("Id")]
public class StatisticalProgram
{
    public string Name { get; set; }
    public Guid Id { get; set; }
    public string ShortName { get; set; }
}

我正在使用Fiddler嗅探请求,请求和响应看起来都很好,但我得到这个错误:

客户端和服务之间存在类型不匹配。类型"(名称空间)。StatisticalProgram'不是实体类型,而是响应有效负载表示实体类型。请确保在客户端上定义的类型与服务的数据模型匹配,或者更新客户端的服务引用

如果我使用其他资源,如odata.org,一切都很好。

<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
    <edmx:DataServices>
        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="ODataDemo">
            <EntityType Name="Product">
                <Key>
                    <PropertyRef Name="ID"/>
                </Key>
                <Property Name="ID" Type="Edm.Int32" Nullable="false"/>
                <Property Name="Name" Type="Edm.String"/>
                <Property Name="Description" Type="Edm.String"/>
                <Property Name="ReleaseDate" Type="Edm.DateTimeOffset" Nullable="false"/>
                <Property Name="DiscontinuedDate" Type="Edm.DateTimeOffset"/>
                <Property Name="Rating" Type="Edm.Int16" Nullable="false"/>
                <Property Name="Price" Type="Edm.Double" Nullable="false"/>
                <NavigationProperty Name="Categories" Type="Collection(ODataDemo.Category)" Partner="Products"/>
                <NavigationProperty Name="Supplier" Type="ODataDemo.Supplier" Partner="Products"/>
                <NavigationProperty Name="ProductDetail" Type="ODataDemo.ProductDetail" Partner="Product"/>
            </EntityType>
            // Other

和映射到这个模型:

public class Product
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

使用它的客户端类是这样的:

public class MyClient<T> where T : class 
{
    private readonly Uri _uri;
    private readonly string _entitySetName;
    public MyClient(Uri uri, string entitySetName)
    {
        _uri = uri;
        _entitySetName = entitySetName;
    }
    public IQueryable<T> Entities()
    {
        var context = new DataServiceContext(_uri, ODataProtocolVersion.V4);
        context.Format.LoadServiceModel = GenerateModel;
        DataServiceQuery<T> query = context.CreateQuery<T>(_entitySetName);
        return query;
    }
    private IEdmModel GenerateModel()
    {
        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<T>(_entitySetName);
        return builder.GetEdmModel();
    }
}

我在Product中这样使用它(效果很好):

var uri = new Uri("http://services.odata.org/V4/OData/OData.svc");
var myClient = new MyClient<Product>(uri, "Products");
var result = myClient.Entities().ToList();

或者像这样的StatisticalProgram(不工作):

var uri = new Uri("http://mylocaluri.com");
var myClient = new MyClient<StatisticalProgram>(uri, "StatisticalPrograms");
var result = myClient.Entities().ToList();

我用

using System.Web.OData.Builder;
using Microsoft.OData.Client;
using Microsoft.OData.Edm;

总结一下。如果我使用odata.org,但不是我的本地OData数据源,它工作得很好。我认为它可能与ID -属性有关,因为它是guid。这会不会打乱映射?如果只与Postman或浏览器一起使用,则本地OData数据源可以很好地工作。因此,映射似乎有一些问题。

消费OData服务时出现错误——客户端和服务之间存在类型不匹配

原来我使用了错误的属性来定义Id -列。

应该是:

[global::Microsoft.OData.Client.Key("Id")]

所以现在我的模型看起来像这样,一切都很好!

[Microsoft.OData.Client.Key("Id")]
public class StatisticalProgram
{
    public string Name { get; set; }
    public Guid Id { get; set; }
    public string ShortName { get; set; }
}