之前介绍过OData 中实现RPC的写法,今天在来一个批量操作。

参考 : https://damienbod.wordpress.com/2014/08/14/web-api-odata-v4-batching-part-10/

http://www.odata.org/getting-started/advanced-tutorial/

public static void Register(HttpConfiguration config)
{
DefaultODataBatchHandler odataBatchHandler = new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer);
odataBatchHandler.MessageQuotas.MaxOperationsPerChangeset = ;
odataBatchHandler.MessageQuotas.MaxPartsPerBatch = ;
config.MapODataServiceRoute("odata", "api", GetModel(), odataBatchHandler);
}

填入DefaultODataBatchHandler就可以了.

前端js

var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:4274/api/$batch", true);
xhr.setRequestHeader("Content-Type", "multipart/mixed; boundary=batch_ebdc0b88-eeb1-4dd6-b170-74331f39bd03");
xhr.setRequestHeader("OData-Version", "4.0");
xhr.setRequestHeader("singleTransaction", "true"); var body = [];
//POST
body.push('--batch_ebdc0b88-eeb1-4dd6-b170-74331f39bd03');
body.push('Content-Type: multipart/mixed; boundary=changeset_54ac09ec-f437-4b08-9925-fd42ed7bd58f');
body.push('');
body.push('--changeset_54ac09ec-f437-4b08-9925-fd42ed7bd58f');
body.push('Content-Type: application/http');
body.push('Content-Transfer-Encoding: binary');
body.push('Content-ID: 1');
body.push('');
body.push('POST http://localhost:4274/api/products HTTP/1.1');
body.push('OData-Version: 4.0');
body.push('Content-Type: application/json;odata.metadata=minimal');
body.push('Accept: application/json;odata.metadata=minimal');
body.push('');
body.push('{"code":"mk100"}');
body.push('--changeset_54ac09ec-f437-4b08-9925-fd42ed7bd58f--'); //PUT
body.push('--batch_ebdc0b88-eeb1-4dd6-b170-74331f39bd03');
body.push('Content-Type: multipart/mixed; boundary=changeset_2346da5e-88c9-4aa5-a837-5db7e1368147');
body.push('');
body.push('--changeset_2346da5e-88c9-4aa5-a837-5db7e1368147');
body.push('Content-Type: application/http');
body.push('Content-Transfer-Encoding: binary');
body.push('Content-ID: 2');
body.push('');
body.push('PUT http://localhost:4274/api/products(1) HTTP/1.1');
body.push('OData-Version: 4.0');
body.push('Content-Type: application/json;odata.metadata=minimal');
body.push('Accept: application/json;odata.metadata=minimal');
body.push('');
body.push('{"id":1,"code":"mk100"}');
body.push('--changeset_2346da5e-88c9-4aa5-a837-5db7e1368147--'); //DELETE
body.push('--batch_ebdc0b88-eeb1-4dd6-b170-74331f39bd03');
body.push('Content-Type: multipart/mixed; boundary=changeset_2346da5e-88c9-4aa5-a837-5db7e1368142');
body.push('');
body.push('--changeset_2346da5e-88c9-4aa5-a837-5db7e1368142');
body.push('Content-Type: application/http');
body.push('Content-Transfer-Encoding: binary');
body.push('Content-ID: 3');
body.push('');
body.push('DELETE http://localhost:4274/api/products(1) HTTP/1.1');
body.push('OData-Version: 4.0');
body.push('Content-Type: application/json;odata.metadata=minimal');
body.push('Accept: application/json;odata.metadata=minimal');
body.push('');
body.push('--changeset_2346da5e-88c9-4aa5-a837-5db7e1368142--'); //GET
body.push('--batch_ebdc0b88-eeb1-4dd6-b170-74331f39bd03');
body.push('Content-Type: application/http');
body.push('Content-Transfer-Encoding: binary');
body.push('Content-ID: 4');
body.push('');
body.push('GET http://localhost:4274/api/products HTTP/1.1');
body.push('OData-Version: 4.0');
body.push('Content-Type: application/json;odata.metadata=minimal');
body.push('Accept: application/json;odata.metadata=minimal');
body.push(''); body.push('--batch_ebdc0b88-eeb1-4dd6-b170-74331f39bd03--');
body.push('');
var data = body.join("\r\n");
xhr.send(data);

从上面代码可以看出,我们所有的请求需要通过一个大请求来包装,把所有的小请求用string写进大请求的body就可以了。

需要特别注意的事string的格式,连空行都是非常重要的哦!

参考 http://www.odata.org/documentation/odata-version-3-0/batch-processing/

虽然这是v3的但是可以看一下, 2.2 Batch Request Body

请求分2中,一种叫changeset,一种叫 operation

changeset 是指那些会改变资源的请求(e.g. POST,PUT,DELETE,ACTION), operation 是指不会改变资源的请求 (e.g. GET,FUNCTION)

代码中可以看出来,这2种写法会有不同。

通常我们在做批量操作时希望会有transaction

这时我们可以扩展 DefaulODataBatchHandle

public class ODataBatchHandlerSingleTransaction : DefaultODataBatchHandler
{
public ODataBatchHandlerSingleTransaction(HttpServer httpServer)
: base(httpServer)
{
} public async override Task<IList<ODataBatchResponseItem>> ExecuteRequestMessagesAsync(IEnumerable<ODataBatchRequestItem> requests,CancellationToken cancellation)
{
if (requests == null) { throw new ArgumentNullException("requests"); }
IList<ODataBatchResponseItem> responses = new List<ODataBatchResponseItem>(); try
{
using (DB db = new DB())
{
using (DbContextTransaction trans = db.Database.BeginTransaction())
{
foreach (ODataBatchRequestItem request in requests)
{
var changeSetResponse = (ChangeSetResponseItem)await request.SendRequestAsync(Invoker, cancellation);
responses.Add(changeSetResponse);
}
bool isAllOk = responses.All(response => ((ChangeSetResponseItem)(response)).Responses.All(r => r.IsSuccessStatusCode));
if (isAllOk)
{
trans.Commit();
}
else
{
trans.Rollback();
}
}
}
}
catch
{
foreach (ODataBatchResponseItem response in responses)
{
if (response != null)
{
response.Dispose();
}
}
throw;
}
return responses;
}
}

拦截以后我们就可以在这一层创建 database Context 和 transaction , controller 内就可以通过任何方式来获取到这里的 context 来做使用.

比如可以使用 Request.Items 来保存传值. (注 : httpRequest 和 httpRequestMessage 是不同的,我们在controller使用的是 message 哦)

还有一点要特别注意的是,如果你需要transaction就不应该有请求,因为GET 请求会在 ExecuteRequestMessagesAsync 之后才执行,如果这时我们释放掉了 database context 那么就会有问题了.

web api 2 学习笔记 (OData Batch request)的更多相关文章

  1. web api 2 学习笔记 (Odata ODataQueryOptions 使用)

    [ODataRoutePrefix("products")] public class ProductController : BaseController { [ODataRou ...

  2. Rest API 开发 学习笔记(转)

    Rest API 开发 学习笔记 概述 REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式.获得这些表徵致使这些应用程序转变了其状态.随着 ...

  3. abp学习(四)——根据入门教程(aspnetMVC Web API进一步学习)

    Introduction With AspNet MVC Web API EntityFramework and AngularJS 地址:https://aspnetboilerplate.com/ ...

  4. Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务

    前言 很久没更新了,之前有很多事情,所以拖了很久,非常抱歉.好了,废话不多说,下面开始正题.本篇仍然使用上一季的的项目背景(系列地址http://www.cnblogs.com/fzrain/p/34 ...

  5. JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?

    前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...

  6. [转]Web Api系列教程第2季(OData篇)(二)——使用Web Api创建只读的OData服务

    本文转自:http://www.cnblogs.com/fzrain/p/3923727.html 前言 很久没更新了,之前有很多事情,所以拖了很久,非常抱歉.好了,废话不多说,下面开始正题.本篇仍然 ...

  7. 《ASP.NET MVC4 WEB编程》学习笔记------Web API 续

    目录 ASP.NET WEB API的出现缘由 ASP.NET WEB API的强大功能 ASP.NET WEB API的出现缘由 随着UI AJAX 请求适量的增加,ASP.NET MVC基于Jso ...

  8. 《ASP.NET MVC4 WEB编程》学习笔记------Web API

    本文截取自情缘 1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集 ...

  9. Asp.net core 学习笔记 ( OData )

    2018-12-10 更新 : 从前我都是把 entity 直接用于 odata 曝露 api 给程序用. 如果这个程序是我们自己写的前端,这样的方式非常好,因为就好比前端可以直接对数据库每一个表做操 ...

随机推荐

  1. 《算法问题实战策略》-chaper13-数值分析

    这一章节主要介绍我们在进行数值分析常用的二分.三分和一个近似求解区间积分的辛普森法. 首先介绍二分. 其实二分的思想很好理解并且笔者在之前的一些文章中也有所渗透,对于二次函数甚至单元高次函数的零点求解 ...

  2. nova-network创建初始化网络

    nova-network创建初始化网络

  3. Python学习打算

    背景:本人用python写自动化脚本,基础的东西都会啦.但是呢,鉴于年轻应该好好学习,所以打算再买一本python书籍用来精读. Python 好的博客: Python快速教程(好多,一点也不快速): ...

  4. Java集合中那些类是线程安全的

    线程安全类 在集合框架中,有些类是线程安全的,这些都是jdk1.1中的出现的.在jdk1.2之后,就出现许许多多非线程安全的类. 下面是这些线程安全的同步的类: vector:就比arraylist多 ...

  5. windows 编程 —— 子窗口 与 子窗口控件

    目录: 子窗口与主窗口的交互 子窗口控件 按钮类别 button 滚动条类别 scrollbar 静态类别  static 编辑框类别 edit 清单方块 listbox 子窗口与主窗口的交互 创建窗 ...

  6. 再次记录老K站点的工作策略

    股市开盘了. 据说今天是多空决战的日子. 7月17日.三大期指交割. 打开大盘,看着指数一会上升,一会跳水.好不欢乐.当然,今天我是来记录我的老K,关于老K的下一步. 近期每天傍晚的时候.都会去江边散 ...

  7. 阻塞机制下的recv小结

    recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结.      首先阻塞 ...

  8. 头像上传ASP.NET MVC实现-可拖动大小实时预览

    这是一个ASP.NET MVC实现的类似于dz论坛的上传头像功能.可以拖动选择大小,支持多种尺寸生成. 效果界面 头像上传源码下载 项目中具体应用时,请根据需求做调整.欢迎交流~回复即可下载~源码下载 ...

  9. Ubuntu 14.04 配置vsftpd实现FTP服务器 - 通过FTP连接AWS

    测试主机:亚马逊AWS EC2 系统:Ubuntu 14.04 想用AWS来做服务器玩,结果发现其不能像简单使用阿里云服务器那样用ftp连接,反正也不熟悉ftp服务器搭建,那就乘这个机会学习一下如何利 ...

  10. 张羿给的删除重复数据的mssql语句

    select count(1), gsdm, idfrom ods_sc.T_D_DEVICE_COMMONgroup by gsdm, idhaving count(1) > 1; delet ...