Asp.net-Web-Api

從 Web Api 2 中的 OData 客戶端呼叫更新檔的正確方法是什麼

  • October 12, 2021

在 web api 團隊創建的 OData 範例之後,我的控制器具有以下支持更新檔:

public HttpResponseMessage Patch([FromODataUri] int key, Delta<Foo> item)
{
 var dbVersion = myDb.GetById(key);
 if(dbVersion == null)
   throw Request.EntityNotFound();

 item.Patch(dbVersion);
 myDb.Update(dbVersion);

 return Request.CreateResponse(HttpStatusCode.NoContent);
}

並使用自動生成的客戶端(派生自DataServiceContext),我送出了一個更新檔請求,如下所示:

var foo = svcContainer.Foos.Where (f => f.Id == 1).SingleOrDefault();
foo.Description = "Updated Description";
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges(SaveChangesOptions.PatchOnUpdate);

但是,在 fiddler 中跟踪呼叫,我看到 Foo 的所有其他屬性都被序列化並發送到服務。這是正確的行為嗎?我只希望通過網路發送 ID 和描述。另外,如果我調試服務方法並呼叫

GetChangedPropertyNames在 item 上,返回其所有屬性名稱。

我應該在客戶端上創建某種 Delta 實例嗎?

我了解服務的斷開連接性質,因此服務端沒有用於跟踪更改的上下文,但在我看來,api 團隊添加了對更新檔的支持是有原因的,所以我想知道客戶端是否應該以不同的方式呼叫更新。

更新

YiDing 提供的連結解釋瞭如何從客戶端創建一個真正的 PATCH 請求(使用上面Microsoft.OData.Client.DataServiceContext創建的Microsoft.OData.Client 6.2.0。為方便起見,這裡是程式碼片段:

var svcContainer = new Default.Container(<svcUri>);
var changeTracker = new DataServiceCollection<Foo>(svcContainer.Foos.Where(f => f.Id == 1));
changeTracker[0].Description = "Patched Description";
svcContainer.SaveChanges();

實現屬性跟踪,並使用此模式,僅將更新的DataServiceCollection屬性發送到服務。不使用DataServiceCollection和簡單使用

svcContainer.UpdateObject(foo);
svcContainer.SaveChanges();

儘管有相反的文件,所有屬性仍然通過網路發送,至少截至Microsoft.OData.Client 6.7.0

Microsoft.OData.Client 版本 6.2.0 現在支持客戶端屬性跟踪。它將僅檢測實體的修改屬性並將更新請求作為 PATCH 而不是 PUT 發送以滿足您的場景要求。有關詳細資訊,請參閱此部落格文章: https ://devblogs.microsoft.com/odata/tutorial-sample-client-property-tracking-for-patch/

引用自:https://stackoverflow.com/questions/21412326