Asp.Net Web API 2第十八課——Working with Entity Relations in OData

來源:互聯網
上載者:User

標籤:

前言

  閱讀本文之前,您也可以到Asp.Net Web API 2 系列導航進行查看 http://www.cnblogs.com/aehyok/p/3446289.html。 

  本文的範例程式碼的為http://pan.baidu.com/s/1o6lqXN8

大多數的資料集定義實體間的關係:客戶有訂單、書籍有作者、產品有供應商。用戶端可以使用OData操作實體間的關係。給定一個產品,你可以找到該產品的供應商。您也可以建立或者刪除關係。例如,您也可以為一個產品設定一個供應商。

  本教程將會展示在Asp.Net Web API中支援這些操作。本文的教程是建立在上一節的教程之上http://www.cnblogs.com/aehyok/p/3545824.html。

Add a Supplier Entity添加一個供應商實體類

首先我們需要來添加一個Supplier的實體類

namespace OData.Models{    public class Supplier    {        [Key]        public string Key { get; set; }        public string Name { get; set; }    }}

這個類使用了一個字串類型的實體鍵。在實踐中,這可能比使用整形鍵不太常見的。但它是值得的看到OData如何處理除了整數以外的其他鍵類型。

接下來,我們將通過在Product類上添加一個Supplier的屬性來建立一個關係。

    public class Product    {        public int ID { get; set; }        public string Name { get; set; }        public decimal Price { get; set; }        public string Category { get; set; }        // New code        [ForeignKey("Supplier")]        public string SupplierId { get; set; }        public virtual Supplier Supplier { get; set; }    }

添加一個新的DbSetProductServiceContext類,從而使Entity Framework將包括Supplier在資料庫表中。

    public class ProductServiceContext : DbContext    {        public ProductServiceContext() : base("name=ProductServiceContext")        {        }        public DbSet<Product> Products { get; set; }        ///New Code        public DbSet<Supplier> Suppliers { get; set; }        }

在WebApiConfig.cs,添加一個“Suppliers”實體的EDM模型:

            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();            builder.EntitySet<Product>("Products");            // New code:            builder.EntitySet<Supplier>("Suppliers");

Navigation Properties導覽屬性

 為了得到一個產品的供應商,用戶端發送了一個Get請求:

GET /Products(1)/Supplier

 在Product類型上有一個Supplier的導覽屬性。在這個執行個體中,Supplier是一個單一的項。但是一個導覽屬性也能返回一個集合(一對多或者多對多的 關係)。

為了支援這個請求,在ProductsController上添加如下方法:

        // GET /Products(1)/Supplier        public Supplier GetSupplier([FromODataUri] int key)        {            Product product = db.Products.FirstOrDefault(p => p.ID == key);            if (product == null)            {                throw new HttpResponseException(HttpStatusCode.NotFound);            }            return product.Supplier;        }

key這個參數就是這個Product的鍵。這個方法返回關聯的實體——在這個執行個體中,就是一個Supplier對象。方法的名稱和參數的名稱都是非常重要的。總之,如果導覽屬性被命名為一個“X”,你需要添加一個被命名為“GetX”的方法。這個方法必須採用一個命名為“key”的參數,用來匹配父類資料類型的key。

它也是很重要的在鍵參數上擁有【FromOdataUri】的屬性。當它從請求的URL中解析鍵時,這個屬性將會告訴Web API去使用Odata文法規則。

Creating and Deleting Links

OData支援建立和刪除兩個實體之間的關係。在OData術語中,這個關係就是一個“link”。每個link有一個攜帶entity/$links/entity的Url。例如,由產品到供應商的連結看起來像這樣:

/Products(1)/$links/Supplier

為了建立一個新的連結,這個用戶端發送了一個post請求到這個連結URI。請求的訊息體就是目標實體的URI。例如,假設有一個供應商的鍵為“CTSO”。為了建立一個連結由“Product(1)”到”Supplier(‘CTSO‘)“,用戶端發送一個請求如下:

POST http://localhost/odata/Products(1)/$links/SupplierContent-Type: application/jsonContent-Length: 50

{"url":"http://localhost/odata/Suppliers(‘CTSO‘)"}

對於刪除一個連結,用戶端發送了一個DELETE 請求到連結URI。

Creating Links

為啟用一個用戶端去建立產品-供應商的連結,需要在ProductsController類中添加如下的代碼:

[AcceptVerbs("POST", "PUT")]public async Task<IHttpActionResult> CreateLink([FromODataUri] int key, string navigationProperty, [FromBody] Uri link){    if (!ModelState.IsValid)    {        return BadRequest(ModelState);    }                Product product = await db.Products.FindAsync(key);    if (product == null)    {        return NotFound();    }                switch (navigationProperty)    {        case "Supplier":            string supplierKey = GetKeyFromLinkUri<string>(link);            Supplier supplier = await db.Suppliers.FindAsync(supplierKey);            if (supplier == null)            {                return NotFound();            }            product.Supplier = supplier;            await db.SaveChangesAsync();            return StatusCode(HttpStatusCode.NoContent);        default:            return NotFound();    }}

這個方法有三個參數:

第一個key:就是引導到父類實體的鍵

第二個navigationProperty: 導覽屬性的名稱。例如,最合適的導覽屬性Supplier。

第三個link:被連結實體的OData的URI。這個值是從訊息體中獲得。例如,這個連結URI可能是”http://localhost/odata/Suppliers(‘CTSO‘)“,也就是供應商中有ID="CTSO"。

這個方法用這個連結去尋找Supplier。如果匹配的供應商被發現,這個方法將會設定Product實體類的Supplier的屬性,並且儲存結果到資料庫。

其中最難的部分是解析連結URI。從根本上來說,你需要類比發送一個get請求到那個URI。接下來的輔助方法將會展示如何處理它。這個方法調用Web API路由過程,返回一個OData實體,展現被轉換的OData路徑。對於一個連結URI,這個片段數中應該有一個實體鍵。

// Helper method to extract the key from an OData link URI.private TKey GetKeyFromLinkUri<TKey>(Uri link){    TKey key = default(TKey);    // Get the route that was used for this request.    IHttpRoute route = Request.GetRouteData().Route;    // Create an equivalent self-hosted route.     IHttpRoute newRoute = new HttpRoute(route.RouteTemplate,         new HttpRouteValueDictionary(route.Defaults),         new HttpRouteValueDictionary(route.Constraints),        new HttpRouteValueDictionary(route.DataTokens), route.Handler);    // Create a fake GET request for the link URI.    var tmpRequest = new HttpRequestMessage(HttpMethod.Get, link);    // Send this request through the routing process.    var routeData = newRoute.GetRouteData(        Request.GetConfiguration().VirtualPathRoot, tmpRequest);    // If the GET request matches the route, use the path segments to find the key.    if (routeData != null)    {        ODataPath path = tmpRequest.GetODataPath();        var segment = path.Segments.OfType<KeyValuePathSegment>().FirstOrDefault();        if (segment != null)        {            // Convert the segment into the key type.            key = (TKey)ODataUriUtils.ConvertFromUriLiteral(                segment.Value, ODataVersion.V3);        }    }    return key;}

Deleting Links

對於刪除一個連結,在ProductsController類中添加如下代碼:

public async Task<IHttpActionResult> DeleteLink([FromODataUri] int key, string navigationProperty){    Product product = await db.Products.FindAsync(key);    if (product == null)    {        return NotFound();    }    switch (navigationProperty)    {        case "Supplier":            product.Supplier = null;            await db.SaveChangesAsync();            return StatusCode(HttpStatusCode.NoContent);        default:            return NotFound();    }}

在這個例子中,這個導覽屬性是一個簡單的Supplier實體。如果導覽屬性是一個集合,對於刪除一個連結的URI必須在被關聯的實體中有一個鍵。例如:

DELETE /odata/Customers(1)/$links/Orders(1)

這裡展示的則是1對多的關係中,刪除其中的一個的例子。

這個請求就是從客戶1中移除訂單為1的。這個DeleteLink方法將會有如下籤名:

void DeleteLink([FromODataUri] int key, string relatedKey, string navigationProperty);

簡單測試結果

 1、http://localhost:3629/Odata/Products(1)/Supplier

2、

 

 將ID=2的Supplier修改為WING

請求Header

POST http://localhost/odata/Products(2)/$links/SupplierContent-Type: application/jsonContent-Length: 50

請求Body

{"url":"http://localhost/odata/Suppliers(‘WING‘)"}

現在再次查看http://localhost/Odata/Products

3、DELETE  http://localhost/odata/Products(2)/$links/Supplier那麼這樣就可以將上面的SupplierId=WING修改為null

然後再次執行http://localhost/Odata/Products查看

 

總結

本文所參考連結為http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/working-with-entity-relations

本文範例程式碼為http://pan.baidu.com/s/1o6lqXN8

Asp.Net Web API 2第十八課——Working with Entity Relations in OData

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.