我使用Simple Odata Client在WPF应用程序中执行CRUD操作。
我有父母&儿童实体:
public class Order
{
public int OrderId{get;set;}
public int Description{get;set;}
public ObservableCollection<OrderLine> OrderLines {get;set;}
}
public class OrderLine
{
public int OrderId{get;set;}
public int OrderLineId{get;set;}
public int ItenId{get;set;}
public int ItemDescription{get;set;}
public virtual Order Order {get;set;}
}
我有一个执行crud操作的课程:
public class ManageOrders
{
//Implements INotifyPropertyChanged
Public Order Order;
public void Get()
{
this.Order = packages = await client
.For<Order>()
.ByKey(1001).
.Expand(x.OrderLines).
.FindEntriesAsync();
}
public void Save()
{
if("NEW")
{
// Add new item and save
}
if("MODIFIED")
{
// save modified item
}
}
public void Delete()
{
//Delete
}
}
我将父实体属性绑定到标题控件。
TextBox.Text = Order.Description;
和子实体到DataGrid。
DataGrid.ItemSource = Order.OrderLines;
单击GET按钮时,将从DB获取订单。 然后我在Order和OrderLines中更改数据。 然后我删除OrderLine并添加两个新的OrderLines。
当我使用ObservarbleCollection
时,更改将自动从UI添加到源。
要求
单击“保存”按钮时,应将所有更改提交给服务器。 (首选批量请求)。
问题
如何通过PATCH请求仅将更改的实体发送到服务器,而不在标题和行中发送未修改的属性?
答案 0 :(得分:2)
您在这里要求的是IMO Web服务和客户端框架的圣杯。
OData中的补丁使得接收和处理对象的已更改属性成为可能并且变得简单。
然而,由客户端来适当地构建数据包,可以通过以下两种方式之一完成:
在发送之前,客户端应将要发送的数据与上次检索的数据进行比较,以确定已更改的属性。
如果客户端上的数据包含在某种视图模型中,则视图模型可以跟踪(或观察)对属性所做的更改。
然后在发送时,客户端必须使用此信息来构建对象图的Delta。
您还没有包含有关如何为后端服务生成URI的任何信息,因此我不想猜测,但是上述两种策略中的一种机制需要是什么实现。
如果您的后端是OData v4服务,那么您可能会发现OData客户端软件包是一个有用的起点。请参阅OData Client library for .NET和以下内容以生成客户端对象图:OData v4 Client Code Generator。您可以对任何实现OData v4规范的服务使用它,而不仅仅是在您控制后端代码时。
支持多种批处理模式,因为批处理通常在OData v4实现中实现不同。出于这个原因,我已经离开了这个讨论的批处理,但是知道这些库本身支持它并且确实很有效。
有关使用生成的类的示例,请参阅以下问题:What is the correct way to call patch from an odata client in web api 2或者按照我的单元测试进行操作:
[TestMethod]
public void TestPatch()
{
var client = ArcoCloud.Gateway.Client.Runtime.GetGatewayClient();
var changeTracker = new Microsoft.OData.Client.DataServiceCollection<ArcoCloud.Gateway.Client.ArcoCloud_DataModel.Device>(client.Devices);
// just change device 96
var device = changeTracker.Single(d => d.Id == 96);
device.Notes = "This is a test note to check if patch works natively";
client.SaveChanges();
/* Traced in Fiddler4
PATCH: {
"@odata.type": "#ArcoCloud_DataModel.Device",
"Notes": "This is a test note to check if patch works natively"
}*/
}
注意这里让客户端只发送修改后的属性是使用从ObservableCollection继承的Microsoft.OData.Client.DataServiceCollection,但是还有一个额外的好处就是保持对其中对象的更改的内部跟踪&#39 ; s查询。见DataServiceCollection Class。
如果确实使用了OData Client Library和Generated类,则可以在不使用DataServiceCollection的情况下轻松查询数据服务,但如果这样做,则更新将使整个对象图形显示。您还会发现保存更改的语法非常冗长且难以使用。这是设计,回写你应该使用DataServiceCollection。该框架提供简单的查询机制,以便您可以简化应用程序中的过程,查询/浏览/过滤数据可以与数据编辑窗口可能用于加载和保存数据的代码隔离。
这是从C#代码与OData v4服务交互的官方MS方式。 T4模板的优点在于您可以根据需要自定义模板或扩展生成的部分类,以便在重新生成类时不会覆盖业务逻辑
如果需要,您可以使用自己的机制来支持此功能,只需记住这两个选项,或者在发生更改时跟踪更改,或者在保存之前使用比较来确定哪些字段已更改。