本文转自:http://www.cnblogs.com/farb/p/ODataAspNetWebAPI.html

开放数据协议(Open Data Protocol【简称OData】)是用于Web的数据访问协议。OData提供了一种对数据集进行CRUD操作(Create,Read,Update,Delete)的统一方式。
Asp.Net Web API支持该协议的v3 和v4版,甚至可以创建一个和v3终结点并排运行的v4终结点。
该博文演示了如何创建支持CRUD操作的OData v4终结点。

用到的软件版本

  • Web API 2
  • OData v4
  • VS 2013 Update 5
  • EF6
  • .Net 4.5.2

创建VS项目

在VS中创建一个新的Asp.Net Web应用项目,命名为“PersonsService”,如下图:

然后继续看下图:

安装OData Nuget包

打开Nuget包管理器控制台,输入以下命令:

Install-Package Microsoft.AspNet.Odata

该命令会安装最新版本的OData Nuget 包。

添加Model类

Model类是一个表示应用中的数据实体的对象。

在解决方案资源管理器中的Models文件夹下,创建一个Person类:

按照惯例,model类应该放在Models文件夹下,但是在你自己的项目中可以不这么做。

下面是我的Person类的代码:

namespace PersonsService.Models
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public bool Gender { get; set; }
public string UserName { get; set; }
}
}

启用Entity Framework

这篇博客,我们使用EF的Code First模式来创建数据库。

Web API OData不要求一定得是EF。只要数据访问层可以将数据库实体转换成model,使用任何数据访问层都可以。

首先,安装EF的Nuget包。在包管理器控制台中使用下面的命令:

Install-Package EntityFramework

打开Web.config文件,在configuration元素中添加下面的connectionStrings节点:

  <connectionStrings>
<add name="PersonsContext" connectionString="Server=.;Database=PersonsDB;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>

接下来,在Models文件夹下添加一个PersonsContext类:

using System.Data.Entity;

namespace PersonsService.Models
{
public class PersonsContext:DbContext
{
public PersonsContext()
: base("name=PersonsContext")
{
} public DbSet<Person> Persons { get; set; }
}
}

在构造函数中,"name=PersonsContext"指定了连接字符串的命名。

配置OData终结点

打开App_Start/WebApiConfig.cs文件,配置下面的新代码(删除自动生成的代码):

using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using PersonsService.Models; namespace PersonsService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{ //新代码
ODataModelBuilder builder=new ODataConventionModelBuilder();
builder.EntitySet<Person>("Persons");
config.MapODataServiceRoute(
routeName:"odata",
routePrefix:"odata",
model:builder.GetEdmModel()
);
}
}
}

上面的代码做了两件事:

  • 创建了一个实体数据模型(Entity Data Model【简称EDM】)。
  • 添加了一个路由。

EDM是一个抽象的数据模型。EDM用于创建服务元数据文档。ODataConventionModelBuilder类使用默认的命名规范创建了一个EDM。这种方式需要写的代码最少。如果你想更多地控制EDM,那么你可以使用 ODataModelBuilder类来创建EDM类,这样做就要显式添加属性,键和导航属性。

路由(route)会告诉Web API如何将HTTP请求路由到终结点。调用MapODataServiceRoute 扩展方法可以创建一个OData v4路由。

如果你的应用有了多个OData终结点,那么要为每个终结点创建一个单独的路由,给每个路由一个唯一的路由名和前缀(prefix)。

添加OData控制器

控制器是处理HTTP请求的一个类。在OData应用中,应该为每个实体集创建一个单独的控制器。而在这篇博客中,我们只要为Person实体创建一个控制器就行了。

在Controllers文件夹下添加一个控制器,如下:

在Controllers文件夹上右键添加控制器,接下来选中上图的选择,因为还没有针对OData v4的基架。

默认已经帮我们生成了下面的代码,基本上我们不需要做什么了,CRUD全都有了,呵呵:

using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using System.Web.OData;
using PersonsService.Models; namespace PersonsService.Controllers
{
/*
在为此控制器添加路由之前,WebApiConfig 类可能要求你做出其他更改。请适当地将这些语句合并到 WebApiConfig 类的 Register 方法中。请注意 OData URL 区分大小写。 using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Extensions;
using PersonsService.Models;
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Person>("Persons");
config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
*/
public class PersonsController : ODataController
{
private PersonsContext db = new PersonsContext(); // GET: odata/Persons
[EnableQuery]
public IQueryable<Person> GetPersons()
{
return db.Persons;
} // GET: odata/Persons(5)
[EnableQuery]
public SingleResult<Person> GetPerson([FromODataUri] int key)
{
return SingleResult.Create(db.Persons.Where(person => person.Id == key));
} // PUT: odata/Persons(5)
public IHttpActionResult Put([FromODataUri] int key, Delta<Person> patch)
{
Validate(patch.GetEntity()); if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} Person person = db.Persons.Find(key);
if (person == null)
{
return NotFound();
} patch.Put(person); try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!PersonExists(key))
{
return NotFound();
}
else
{
throw;
}
} return Updated(person);
} // POST: odata/Persons
public IHttpActionResult Post(Person person)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} db.Persons.Add(person);
db.SaveChanges(); return Created(person);
} // PATCH: odata/Persons(5)
[AcceptVerbs("PATCH", "MERGE")]
public IHttpActionResult Patch([FromODataUri] int key, Delta<Person> patch)
{
Validate(patch.GetEntity()); if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} Person person = db.Persons.Find(key);
if (person == null)
{
return NotFound();
} patch.Patch(person); try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!PersonExists(key))
{
return NotFound();
}
else
{
throw;
}
} return Updated(person);
} // DELETE: odata/Persons(5)
public IHttpActionResult Delete([FromODataUri] int key)
{
Person person = db.Persons.Find(key);
if (person == null)
{
return NotFound();
} db.Persons.Remove(person);
db.SaveChanges(); return StatusCode(HttpStatusCode.NoContent);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
} private bool PersonExists(int key)
{
return db.Persons.Count(e => e.Id == key) > 0;
}
}
}

该控制器借助EF,使用PersonsContext类来访问数据库。注意控制器重写了Dispose方法来释放 PersonsContext

生成数据库

通过Code First的Migration生成数据库,然后填充数据。关于如何使用CodeFirst生成数据库不是本节的重点,所以这里一笔带过。下面是我生成的数据库已经填充的数据:

查询实体集

自动生成的查询操作如下:

 // GET: odata/Persons
[EnableQuery]
public IQueryable<Person> GetPersons()
{
return db.Persons;
} // GET: odata/Persons(5)
[EnableQuery]
public SingleResult<Person> GetPerson([FromODataUri] int key)
{
return SingleResult.Create(db.Persons.Where(person => person.Id == key));
}

无参数的GetPersons()方法会返回整个Person表的集合。
GetPerson([FromODataUri] int key)方法会返回指定Id的Person。

[EnableQuery]特性允许客户端使用查询选项(如$filter,$sort和$page)修改查询。

操作演示

新增实体

允许客户端将一个新的Person实体添加到数据库中:

// POST: odata/Persons
public IHttpActionResult Post(Person person)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} db.Persons.Add(person);
db.SaveChanges(); return Created(person);
}

更新实体

OData支持两种不同语义更新实体,包括PATCH和PUT。

  • PATCH执行一个部分更新,客户端只识别要更新的属性。
  • PUT会替换整个实体。

PUT的劣势在于客户端必须发送实体的所有属性,包括没有改变的值。
OData说明书陈述了PATCH是首选。

下面是生成的代码:

// PATCH: odata/Persons(5)
[AcceptVerbs("PATCH", "MERGE")]
public IHttpActionResult Patch([FromODataUri] int key, Delta<Person> patch)
{
Validate(patch.GetEntity()); if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} Person person = db.Persons.Find(key);
if (person == null)
{
return NotFound();
} patch.Patch(person); try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!PersonExists(key))
{
return NotFound();
}
else
{
throw;
}
} return Updated(person);
}

在PATCH中,控制器使用了Delta类型来跟踪改变。

删除实体

允许客户端从数据库删除一个Person:

// DELETE: odata/Persons(5)
public IHttpActionResult Delete([FromODataUri] int key)
{
Person person = db.Persons.Find(key);
if (person == null)
{
return NotFound();
} db.Persons.Remove(person);
db.SaveChanges(); return StatusCode(HttpStatusCode.NoContent);
}
好文要顶
如果您认为这篇文章还不错或者有所收获,您可以通过右边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击右下角的【好文要顶】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力!
作者:tkb至简
声明:原创博客请在转载时保留原文链接或者在文章开头加上本人博客地址,如发现错误,欢迎批评指正。凡是转载于本人的文章,不能设置打赏功能,如有特殊需求请与本人联系!

[转]使用ASP.NET Web API 2创建OData v4 终结点的更多相关文章

  1. 使用ASP.NET Web API 2创建OData v4 终结点

    开放数据协议(Open Data Protocol[简称OData])是用于Web的数据访问协议.OData提供了一种对数据集进行CRUD操作(Create,Read,Update,Delete)的统 ...

  2. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  3. ASP.NET Web API 过滤器创建、执行过程(一)

    ASP.NET Web API 过滤器创建.执行过程(一) 前言 在上一篇中我们讲到控制器的执行过程系列,这个系列要搁置一段时间了,因为在控制器执行的过程中包含的信息都是要单独的用一个系列来描述的,就 ...

  4. ASP.NET Web API 控制器创建过程(二)

    ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...

  5. ASP.NET Web API 控制器创建过程(一)

    ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...

  6. ASP.NET Web API中使用OData

    在ASP.NET Web API中使用OData 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在ASP.NET Web API中,对于CRUD(creat ...

  7. 在ASP.NET Web API中使用OData

    http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...

  8. Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)

    前言 很久没更新博客了,加上刚过年,现在准备重新开战,继续自己的学习之路.本文已同步到Web API2系列文章中http://www.cnblogs.com/aehyok/p/3446289.html ...

  9. 在ASP.NET Web API中使用OData的Action和Function

    本篇体验OData的Action和Function功能.上下文信息参考"ASP.NET Web API基于OData的增删改查,以及处理实体间关系".在本文之前,我存在的疑惑包括: ...

随机推荐

  1. PDF文档转换为图片、图片转成PDF 及PDF合并

    简介 功能:PDF文档按每页转换成一张图片,一张图片转换成一张PDF 并将多张PDF合成一个多页的PDF文档. 经历:在各个网站上搜索始终出现各种问题,尤其是遇到引用的版本问题尤其头疼,不是不能适用当 ...

  2. 类似gitlab代码提交的热力图怎么做?

    本文由  网易云发布. 作者:张淞(本篇文章仅限知乎内部分享,如需转载,请取得作者同意授权.) 昨夜,网易有数产品经理路过开发的显示屏前见到了类型这样的一张图: 于是想到有数能不能做出这样的图来?作为 ...

  3. 50余本中外Python电子教程及源码下载地址

    链接:http://pan.baidu.com/s/1c0VTwsC 密码:hapu

  4. P1642 规划

    题目链接 题意分析 一看就知道是一道\(01\)分数规划的题 我们二分值之后 跑树形背包就可以了 CODE: #include<iostream> #include<cstdio&g ...

  5. 论文笔记:CNN经典结构2(WideResNet,FractalNet,DenseNet,ResNeXt,DPN,SENet)

    前言 在论文笔记:CNN经典结构1中主要讲了2012-2015年的一些经典CNN结构.本文主要讲解2016-2017年的一些经典CNN结构. CIFAR和SVHN上,DenseNet-BC优于ResN ...

  6. 44.oracle表空间的使用

    要给下属充分的发挥空间,要允许下属犯错,下属犯错自己能顶下来就顶着,不要盯得让下属觉得“这不是我的事,我只是个小打工的”,团建要放在首位.不可在下属面前“装B”,别人也不傻. Oracle数据库开创性 ...

  7. [原创]php任务调度器 hellogerard/jobby

    目录 简介 安装 标准使用 选项 项目实践 简介 一个强大的php层面上的定时任务调度器, 无需修改系统层面的crontab 实际中, php 结合 crontab 来实现定时任务是一种经得住考验的实 ...

  8. 用 Hystrix 构建高可用服务架构

    1 hystrix是什么 在分布式系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是依赖服务,有的时候某些依赖服务出现故障也是很正常的. Hystrix 可以让我们在分布式系统中对服务间的 ...

  9. centos7嵌入式环境搭建

    1. 在网上搜索下载交叉编译器arm-linux-gcc文件,我下载的是:arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 ...

  10. 非常不错的app和网站

    置顶: word.pdf之间相互转换的网站: https://www.addpdf.cn 很棒啊 1. Global Potplayer 这个软件简直了,播放各种视频, 无论是本地的,还是在线的,都非 ...