servicestack,updates,Rest,servicestack,Updates" /> servicestack,updates,Rest,servicestack,Updates" />

如何使用restful API实现对象属性更新?

如何使用restful API实现对象属性更新?,rest,servicestack,updates,Rest,servicestack,Updates,使用ServiceStack(面向消息的RESTfulWeb服务)实现对象属性更新的正确方法是什么 如果客户端需要更新Foo.bar并且只有Foo的id 我应该接受包含Foo id和Foo.bar值的FooBarUpdate请求对象吗? 这意味着我必须为每个属性更新创建单独的请求,或者至少为那些我希望更新的属性(或它们的组合)创建单独的请求。这似乎也不符合RESTful标准 或者,如果我接受一个包含整个具有更新属性的Foo的Foo请求对象,那么客户端首先需要检索Foo,然后服务将检查哪些属性已更

使用ServiceStack(面向消息的RESTfulWeb服务)实现对象属性更新的正确方法是什么

如果客户端需要更新Foo.bar并且只有Foo的id

我应该接受包含Foo id和Foo.bar值的FooBarUpdate请求对象吗? 这意味着我必须为每个属性更新创建单独的请求,或者至少为那些我希望更新的属性(或它们的组合)创建单独的请求。这似乎也不符合RESTful标准

或者,如果我接受一个包含整个具有更新属性的Foo的Foo请求对象,那么客户端首先需要检索Foo,然后服务将检查哪些属性已更新。这似乎是不必要的开销

最后,如果我接受一个Foo请求,但只使用id和修改的属性值(Foo.bar),那么Foo对象是不完整的,根据其他帖子,这可能会导致混淆,因为有人认为它是完整的对象。

如何处理RESTful更新: 如果
Bar
Foo
上的一个单独属性,那么就没有理由不让一个
updateforequest
包含更新的
Bar

像这样:

[Route(“/foo/{Id}”,“POST”)]
公共类UpdateForeQuest
{
公共int Id{get;set;}
公共条{get;set;}
}
但是,如果
Bar
是一个集合,那么Foo是:

公共类Foo
{
公共int Id{get;set;}
公共条[]条{get;set;}
}
然后,更新
Foo
上的
Bar
项的更安全的方法是通过
Foo
路径引用
Bar
的实例。但您需要知道该条的id(或集合中与其
Foo
相关的索引)

[路由(“/foo/{FooId}/bar/{Id}”,“POST”)]
公共类UpdateForRequest:Bar
{
公共int FooId{get;set;}
}

在服务器上处理部分更新 为解决这些问题:

或者,如果我接受一个
Foo
请求对象,该对象包含具有更新属性的整个Foo,则客户端首先需要检索Foo,然后服务将检查哪些属性已更新。这似乎是不必要的开销

你唯一需要关心整个
Foo
的时间是在创建
Foo
时,它会有自己的路线。所以这里应该没有什么可担心的

[路线(“/foo”,“POST”)]
公共类CreateFooRequest
{
...
}
更新
Foo
时,您将发布到一个现有的Foo路由,如下
/Foo/123

[Route(“/foo/{Id}”,“POST”)]
公共类UpdateForeQuest
{
公共int Id{get;set;}
...
}
最终,您的服务应该能够指示ORM只更新请求中包含的字段以及更改。因此,如果请求只有几个更改,那么ORM将处理这些更改

例如,ORMLite更新简单如下:

db.Update(updateForeQuest);
这将仅使用在请求中找到的字段,在由
Id
标识的行上创建SQL
UPDATE

如果发送了一个完整的
Foo
,则允许ORM将其视为更改了许多字段,记录将被覆盖。正如您所建议的,您可以在更新之前查找记录并确定更改的字段,但正如您所说,这是不必要的开销

通常,如果更新方法处理部分更改,那么发送整个
Foo
应该没有问题,但理想情况下,客户端应该只发送更改

最后,如果我接受一个Foo请求,但只有id和修改后的属性值(Foo.bar),那么Foo对象是不完整的,根据其他帖子,这可能会导致混淆,有人认为它是一个完整的对象

最后一行有人假设它是一个完整的对象,这有点令人担忧。更新路由应仅用于更新,您不应在此处使用完整对象。update方法应该期望请求
Foo
是部分的,并按照上面的解释进行处理


我认为您可能应该看到一些很好的例子,说明如何将部分更新应用于现有数据。虽然没有必要选择ORM,但基本概念适用于其他ORM,我认为这很好地说明了它们


按名称更新
Foo
上集合中的项目
Bar

那样做很不传统。使用具有含义的值(如名称)的缺点是,您无法轻松更改此属性,因为它是一个标识符。如果它是静态的,那么就可以了

所以
Foo
看起来像这样:

db.Update(updateBarRequest, p => p.FooId == updateBarRequest.FooId && p.Name == updateBarRequest.Name);
公共类Foo
{
公共int Id{get;set;}
公共条[]条{get;set;}
}
让我们假设
Bar

公共类栏
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共int Baz{get;set;}
公共布尔值已启用{get;set;}
}
如果我正在使用条形图的
Name
而不是
Id
进行更新,则无法更改
Name
属性,因为这样我就不知道要更新哪个条形图。我现在需要一条全新的路线来处理酒吧名称的变更

如果您决定将其用作集合中的标识符,您可以执行以下操作:

[路由(“/foo/{FooId}/bar/{Name}”,“POST”)]
公共类UpdateForRequest:Bar
{
公共int FooId{get;set;}
}
因此,要在名为“Bob”的条上用更新的
Baz=13
IsEnabled=false
更新Foo 123

POST/foo/123/bar/Bob
{
巴兹:13,,
我被逮到了:错
}
在y