OData客户端无法为键属性发送空值

jon*_*ert 2 c# odata

我建立了一个OData WebAPI服务,该服务公开了几个实体(使用OData 4,System.Web.Odata v5.1.9)。

该服务接受POST(用于创建)和PATCH(用于更新)。在内部,POST和PATCH都转发到Oracle数据库,并且这两种方法都是通过单个存储过程处理的,该存储过程将Id作为输入参数。如果Id为空,则创建新记录,否则更新具有该Id的记录。

最近,我们的一位消费者抱怨他们无法正确插入新数据。问题在于他们使用OData客户端使用元数据生成模型。由于Id不可为空,因此始终向我的服务发送0,这提示数据库例程使用ID 0(不存在,引发异常)更新记录。

现在,我看到有两种选择可以避免这种情况:

  • 在我的控制器中检查Id是否为default(int),如果是,则将NULL传递给SP
  • 停止使用OData客户端,让他们手动构造其消息
  • 将单个存储过程分为两个过程(插入和更新)
  • 将Id属性更改为字符串

我的实体类如下所示:

public class ContactDTO
    {
        [Key]
        public int Id { get; set; }

        [ForeignKey("Person")]
        public int? PersonId { get; set; }

        // snip some other properties
    }
Run Code Online (Sandbox Code Playgroud)

由于Id属性定义为[Key],因此在元数据中显示为Required:

<EntityType Name="ContactDTO">
    <Key>
        <PropertyRef Name="Id"/>
    </Key>
    <Property Name="Id" Type="Edm.Int32" Nullable="false"/>
    <Property Name="PersonId" Type="Edm.Int32"/>
</EntityType>
Run Code Online (Sandbox Code Playgroud)

我有一种感觉,我在这里遗漏了一些东西,也许我应该将其保留不变,但是如果没有,我可以采取哪些步骤来确保他们可以正确地致电我的服务

And*_*toy 5

  1. Id属性定义为可为空,并删除该属性KeyAttribute

    public class ContactDTO
    {
        public int? Id { get; set; }    
    
        [ForeignKey("Person")]
        public int? PersonId { get; set; }
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  2. Id属性配置为键和可选:

    ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder();
    
    modelBuilder.EntityType<ContactDTO>().HasKey(_ => _.Id);
    
    modelBuilder.EntityType<ContactDTO>().Property(_ => _.Id).IsOptional();
    
    Run Code Online (Sandbox Code Playgroud)

它产生以下元数据:

<EntityType Name="ContactDTO">
    <Key>
        <PropertyRef Name="Id" />
    </Key>
    <Property Name="Id" Type="Edm.Int32" />
    <Property Name="PersonId" Type="Edm.Int32" />
</EntityType>
Run Code Online (Sandbox Code Playgroud)