快速搭建WebAPI(Odata+Code-First)附Odata條件查詢表~
阿新 • • 發佈:2018-11-15
Odata是什麼?
開放資料協議(Open Data Protocol,縮寫OData)是一種描述如何建立和訪問Restful服務的OASIS標準。該標準由微軟發起,前三個版本1.0、2.0、3.0都是微軟開放標準,遵循 [1] 。第四個版本4.0於2014年3月17日在OASIS投票通過成為開放工業標準 [2] 。
為什麼需要OData?
OData是一個協議,一個標準。所以這個問題等同於為什麼我們需要協議。類比TCP協議就可以理解一般。假設你開發的元件必須要和某個第三方元件通訊,如果第三方元件不支援TCP而只支援其內部開發的一個私有協議,你就肯定頭大了,你必須在你的元件裡單獨為其實現這個私有協議。如果大家都支援TCP協議,不就省事了麼。這就是標準協議的作用:協議和標準用於制定一個統一通用的規則。 我們只需要按照這個協議或標準生產元件,那麼這個元件就可以方便的和其他元件整合/協作。而無須根據其他元件的私有標準定製化元件。
如何使用OData?
Odata目前已經不怎麼更新了,目前最高的5.7已經停留在2015年8月21 遠古時代,然後我們還需要在WebApiConfig.cs中配置Odata
ODataModelBuilder builder = new ODataConventionModelBuilder(); builder.EntitySet<TRoles>("TRoles"); builder.EntitySet<TUsers>("TUsers"); builder.EntitySet<TUsersRoles>("TUsersRoles"); config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
其中builder.EntitySet<TRoles>("TRoles"); 需要注意的是EntitySet這個方法是對你的實體類進行配置,其底層是要獲取的型別放到它的配置項裡。
Code-First 方式 create DataBase
Context.cs
public Model1() : base("name=CodeFirstDemo") { } public DbSet<TUsers> Users { get; set; } public DbSet<TRoles> Roles { get; set; } public DbSet<TUsersRoles> UsersRoles { get; set; }
其它的三個類就不寫上來了,不想佔用部落格園的資源,也不想寫沒有意義的!
建立webAPIController
建立完的程式碼展示:
using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using System.Web.Http.ModelBinding; using System.Web.Http.OData; using System.Web.Http.OData.Routing; using heheda.Models; namespace heheda.Controllers { /* The WebApiConfig class may require additional changes to add a route for this controller. Merge these statements into the Register method of the WebApiConfig class as applicable. Note that OData URLs are case sensitive. using System.Web.Http.OData.Builder; using System.Web.Http.OData.Extensions; using heheda.Models; ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntitySet<TRoles>("TRoles"); builder.EntitySet<TUsersRoles>("UsersRoles"); config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel()); */ public class TRolesController : ODataController { private Model1 db = new Model1(); // GET: odata/TRoles [EnableQuery] public IQueryable<TRoles> GetTRoles() { return db.Roles; } // GET: odata/TRoles(5) [EnableQuery] public SingleResult<TRoles> GetTRoles([FromODataUri] int key) { return SingleResult.Create(db.Roles.Where(tRoles => tRoles.Id == key)); } // PUT: odata/TRoles(5) public IHttpActionResult Put([FromODataUri] int key, Delta<TRoles> patch) { Validate(patch.GetEntity()); if (!ModelState.IsValid) { return BadRequest(ModelState); } TRoles tRoles = db.Roles.Find(key); if (tRoles == null) { return NotFound(); } patch.Put(tRoles); try { db.SaveChanges(); } catch (DbUpdateConcurrencyException) { if (!TRolesExists(key)) { return NotFound(); } else { throw; } } return Updated(tRoles); } // POST: odata/TRoles public IHttpActionResult Post(TRoles tRoles) { if (!ModelState.IsValid) { return BadRequest(ModelState); } db.Roles.Add(tRoles); db.SaveChanges(); return Created(tRoles); } // PATCH: odata/TRoles(5) [AcceptVerbs("PATCH", "MERGE")] public IHttpActionResult Patch([FromODataUri] int key, Delta<TRoles> patch) { Validate(patch.GetEntity()); if (!ModelState.IsValid) { return BadRequest(ModelState); } TRoles tRoles = db.Roles.Find(key); if (tRoles == null) { return NotFound(); } patch.Patch(tRoles); try { db.SaveChanges(); } catch (DbUpdateConcurrencyException) { if (!TRolesExists(key)) { return NotFound(); } else { throw; } } return Updated(tRoles); } // DELETE: odata/TRoles(5) public IHttpActionResult Delete([FromODataUri] int key) { TRoles tRoles = db.Roles.Find(key); if (tRoles == null) { return NotFound(); } db.Roles.Remove(tRoles); db.SaveChanges(); return StatusCode(HttpStatusCode.NoContent); } // GET: odata/TRoles(5)/TRolesUsersList [EnableQuery] public IQueryable<TUsersRoles> GetTRolesUsersList([FromODataUri] int key) { return db.Roles.Where(m => m.Id == key).SelectMany(m => m.TRolesUsersList); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } private bool TRolesExists(int key) { return db.Roles.Count(e => e.Id == key) > 0; } } }
在之後我們就可以在前端中去通過這個協議規則去過濾我們的資料了!
Odata篩選資料規則表
操作 |
URL |
說明 |
$filter | http://localhost:8090/api/Meetings?$filter=ProductName eq 'Tofu' | 根據表示式的狀態返回結果(返回ProductName 等於Tofu的Products) |
$orderby | http://localhost:8090/api/Meetings?$orderby=ProductName | 根據結果排序(根據ProductName列排序) |
$skip | http://localhost:8090/api/Meetings?$skip=10 | 越過結果中的n條資料,常用於分頁 |
$top | http://localhost:8090/api/Meetings?$top=10 | 返回結果中的前n條記錄,常用於分頁 |
$select | http://localhost:8090/api/Meetings?$filter=ProductName eq 'Tofu'&$select=ProductName,UnitPrice | 選擇需要返回的屬性 |
$expand | http://localhost:8090/api/Meetings?$expand=Supplier | 返回Products中包含的導航屬性(關聯屬性)Supplier |
$inlinecount | http://localhost:8090/api/Meetings?$inlinecount=allpages | 向伺服器獲取符合條件的資源總數(分頁的total值) |