本文属于OData系列html
目录web
- 武装你的WEBAPI-OData入门
- 武装你的WEBAPI-OData便捷查询
- 武装你的WEBAPI-OData分页查询
- 武装你的WEBAPI-OData资源更新Delta
- 武装你的WEBAPI-OData之EDM
- 武装你的WEBAPI-OData常见问题
- 武装你的WEBAPI-OData使用Endpoint
OData不光提供了数据查询的便捷手段,它也提供了数据更新的方便办法。数据库
通常用于数据更新的方式,最多的就是PUT和PATCH方法了。关于这两个方法的区别以及介绍,能够翻看我以前写的RESTful设计中的常见疑问。json
举例说明:c#
[AllowAnonymous] [HttpPut] [ProducesResponseType(typeof(ReturnData<CarInfo>), Status200OK)] [ProducesResponseType(typeof(ReturnData<string>), Status409Conflict)] public async Task<ActionResult> Put([FromBody] Models.CarInfo value) { var info = new Info<CarInfo>(); var res = await info.Put(value); if (res != null) return Ok(new ReturnData<CarInfo>(res)); else return Conflict(new ReturnData<string>("数据已经存在")); } [HttpPatch()] [Authorize(Roles = "Administrator, Supervisor")] [ProducesResponseType(typeof(ReturnData<CarInfo>), Status200OK)] [ProducesResponseType(typeof(ReturnData<string>), Status404NotFound)] public async Task<ActionResult> Patch([FromBody] Models.CarInfo value) { var info = new Info<CarInfo>(); var res = await info.Patch(value); if (res != null) return Ok(new ReturnData<CarInfo>(res)); else return NotFound(new ReturnData<string>("没法找到原数据")); } public async ValueTask<T?> Put(T value) { //只列出关键代码 var res = await dbset!.FindAsync(key.GetValue(value) as string); if (res != null) { //return null; context.Entry(res).CurrentValues.SetValues(value); } else { value.CreateDate = DateTime.Now; dbset.Add(value); await context.SaveChangesAsync(); return value; } }
Put和Patch方法主要是实现数据库对应实体的替换逻辑,这里我就不贴详细的代码了。api
能够发现,我须要传入的是一个CarInfo的对象,替换这个对象,咱们就能够实现资源的更新了。app
固然用上面这个方式能够实现资源的更新,不过也存在几个问题:async
OData提供了一个叫作Delta<>的泛型类,Delta就是Δ,物理里面通常用来表示变化量。OData的这个类,也是用来表示一个对象的变化的。设计
[Table("deviceinfo")] public class DeviceInfo { [Key] [MaxLength(200)] public string DeviceId { get; set; } public string CameraId { get; set; } public string AppKey { get; set; } public string AppSecret { get; set; } public string Name { get; set; } public string DeviceType { get; set; } public string Location { get; set; } public string Description { get; set; } } [Produces("application/json")] [ProducesResponseType(typeof(Order), Status200OK)] [ProducesResponseType(Status400BadRequest)] [Authorize(Roles ="Administrator")] [ODataRoute("({id})")] public async Task<IActionResult> Patch(string id, Delta<DeviceInfo> delta) { if (!ModelState.IsValid) return BadRequest(new ODataError() { ErrorCode = "400", Message = "Data is not valid" }); var infos = await _context.DeviceInfoes.FindAsync(id); delta.GetInstance().CameraId = infos.CameraId; delta.Patch(infos); //得到更改过的属性名称 var ps = delta.GetChangedPropertyNames(); await _context.SaveChangesAsync(); return Ok(); }
使用Delta<>的时候,不须要发送对象的所有属性,只须要发送变化的部分便可。对于上面的请求,咱们只须要发送Key属性(用于肯定数据)和变化的属性便可。另外,delta提供了追踪变化的一系列方法:GetChangedPropertyNames()
之类的,能够很方便地继续手动处理,也提供了GetInstance()
方法得到数据对象,能够很方便的进行拓展。code
通常使用的话,Delta还提供Post和Put方法,和WebAPI定义的行为一致,这样用起来也很是直观。
OData提供了Delta泛型,可以包装咱们的数据对象,能够极大地简化资源更新的开发工做。