我已经建立了一个ODATA WebAPI服务,以公开几个实体(使用ODATA 4,System.Web.odata v5.1.9)。
服务接受BOST帖子(用于创建)和补丁(用于更新)。在内部,POST和PAITS均被转发到Oracle数据库,并且通过单个存储过程来处理这两种方法,该过程将ID作为输入参数。如果ID为null,则创建新记录,否则已更新了具有该ID的记录。
最近我们的一位消费者抱怨说,他们无法正确插入新数据。问题在于他们使用ODATA客户端使用元数据来生成其模型。由于ID不可自然,总是将0发送到我的服务,并提示数据库例程使用ID 0进行记录更新(不存在,提高例外)。
现在,我看到有几个选项可以绕过以下内容:
- 在我的控制器中检查ID是否默认(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
}
由于ID属性定义为[键],因此根据需要在元数据中显示:
<EntityType Name="ContactDTO">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false"/>
<Property Name="PersonId" Type="Edm.Int32"/>
</EntityType>
我有一种感觉,我在这里错过了一些东西,也许我应该像以前一样离开它,但是如果没有,我可以采取什么步骤来确保他们可以正确地致电我的服务
-
将
Id
属性定义为无效,然后在其上删除KeyAttribute
:public class ContactDTO { public int? Id { get; set; } [ForeignKey("Person")] public int? PersonId { get; set; } }
-
将
Id
属性配置为键,并将其配置为可选:ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder(); modelBuilder.EntityType<ContactDTO>().HasKey(_ => _.Id); modelBuilder.EntityType<ContactDTO>().Property(_ => _.Id).IsOptional();
它产生以下元数据:
<EntityType Name="ContactDTO">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" />
<Property Name="PersonId" Type="Edm.Int32" />
</EntityType>