使用Simple.OData.Client仅更新某些属性

时间:2018-11-29 09:44:59

标签: c# simple.odata simple.odata.client

我正在使用Simple.OData.Client,我想更新实体的某些属性。

假设我在C#中有以下课程:

[DataContract(Name = "entity")]
public class MyEntity
{
        [DataMember(Name = "propertyA")]
        public string MyPropertyA { get; set; }

        [DataMember(Name = "propertyB")]
        public string MyPropertyB { get; set; }
}

我正在尝试像这样更新propertyA:

await _simpleOdataClient.For<MyEntity>()
                  .Key(key)
                  .Set(new MyEntity
                  {
                    MyPropertyA = "test"
                  })
                  .UpdateEntryAsync();

我以这个为例:https://github.com/object/Simple.OData.Client/wiki/Updating-entries

我的问题是,发送一个带有propertyA = test但propertyB = null的PUT请求。它会尝试为我不想更改的属性设置null值。

是否可以仅更新某些属性并在OData请求中发送HTTP PATCH?

3 个答案:

答案 0 :(得分:1)

您应该使用 PATCH 而不是 PUT。

HTTP Standard 说:

<块引用>

给定表示的成功 PUT 将表明对同一目标资源的后续 GET 将导致在 200 (OK) 响应中发送等效表示。

因此,如果您在请求中发出只有 MyPropertyA 的 PUT,那么后续的 GET 应该返回一个带有 MyPropertyB 作为 null 的实体。

主要是,OData v4 Standard 表示:

<块引用>

支持 PUT 的服务必须用请求正文中指定的值替换结构属性的所有值。缺少未定义为引用约束内的依赖属性的非关键、可更新结构属性必须设置为其默认值

虽然您可以让客户端不发送 MyPropertyB,但适当的 OData 服务器必须将其解释为将值设置为默认(空)的请求。< /p>

答案 1 :(得分:0)

您应该使用匿名对象来执行此操作,或者找到某种方式来配置客户端的序列化器以忽略默认值(例如,引用类型为null)。

await _simpleOdataClient.For<MyEntity>()
                  .Key(key)
                  .Set(new
                  {
                    MyPropertyA = "test"
                  })
                  .UpdateEntryAsync();

答案 2 :(得分:0)

您可以使用类型化的Fluent API来实现。

您必须为读取(.Select)明确选择字段,并在写入(.Set)时明确设置它们,以防止发送整个结构。

我认为你快到了。 代替 .Set(new MyEntity ),使用 .Set(new

我还使用填充的实体实例和简化的.Set

              .Set(new 
              {
                myEntity.MyPropertyA,
              })

等效于

              .Set(new 
              {
                MyPropertyA = myEntity.MyPropertyA,
              })

一切都应该正常进行。 除非DataContract以某种方式引起了问题。 在我的工作示例中,该类没有DataContract属性。 经Fiddler验证,仅发送指定的字段(在我的代码中)。

 var myEntity = new MyEntity() 
 {
    MyPropertyA = "test"
 };

 await _simpleOdataClient.For<MyEntity>()
              .Key(key)
              .Set(new 
              {
                myEntity.MyPropertyA,
              })
              .UpdateEntryAsync();