Simple.Odata.Client - 仅通过向服务器发送修改后的属性来实现Odata Patch实体

时间:2017-03-10 07:49:12

标签: c# wpf odata odata-v4 simple.odata.client

我使用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
    }   
}

enter image description here

我将父实体属性绑定到标题控件。

TextBox.Text = Order.Description;

和子实体到DataGrid。

DataGrid.ItemSource = Order.OrderLines;

单击GET按钮时,将从DB获取订单。 然后我在Order和OrderLines中更改数据。 然后我删除OrderLine并添加两个新的OrderLines。

当我使用ObservarbleCollection时,更改将自动从UI添加到源。

要求

单击“保存”按钮时,应将所有更改提交给服务器。 (首选批量请求)。

问题

如何通过PATCH请求仅将更改的实体发送到服务器,而不在标题和行中发送未修改的属性?

1 个答案:

答案 0 :(得分:2)

您在这里要求的是IMO Web服务和客户端框架的圣杯。

OData中的补丁使得接收和处理对象的已更改属性成为可能并且变得简单。

然而,由客户端来适当地构建数据包,可以通过以下两种方式之一完成:

  1. 在发送之前,客户端应将要发送的数据与上次检索的数据进行比较,以确定已更改的属性。

  2. 如果客户端上的数据包含在某种视图模型中,则视图模型可以跟踪(或观察)对属性所做的更改。

  3. 然后在发送时,客户端必须使用此信息来构建对象图的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模板的优点在于您可以根据需要自定义模板或扩展生成的部分类,以便在重新生成类时不会覆盖业务逻辑

    如果需要,您可以使用自己的机制来支持此功能,只需记住这两个选项,或者在发生更改时跟踪更改,或者在保存之前使用比较来确定哪些字段已更改。