标签:style blog http io color ar os for sp
1.概述
本例是在学习系列07介绍的项目基础上进行演练……
2.添加实体
在Models文件夹下,添加Supplier.cs类,代码:
using System.Collections.Generic;
namespace ProductService.Models
{
public class Supplier
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection Products { get; set; }
}
}
修改Models\Product.cs,代码(添加外键和导航属性):
using System.ComponentModel.DataAnnotations.Schema;
namespace ProductService.Models
{
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
[ForeignKey("Supplier")]
public int? SupplierId { get; set; }
public virtual Supplier Supplier { get; set; }
}
}
修改Models\EFContext.cs,代码(添加EF实体集):
using System.Data.Entity;
namespace ProductService.Models
{
public class EFContext : DbContext
{
public EFContext() : base("name=ProductContext") { }
public DbSet Products { get; set; }
public DbSet Suppliers { get; set; }
}
}
修改App_Start\WebApiConfig.cs,代码(添加实体数据模型):
using ProductService.Models;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
namespace ProductService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务
//创建实体数据模型 (EDM)
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet("Products");
builder.EntitySet("Suppliers");
//添加路由
config.MapODataServiceRoute(routeName: "ODataRoute", routePrefix: null, model: builder.GetEdmModel());
// Web API 路由
//config.MapHttpAttributeRoutes();
//config.Routes.MapHttpRoute(
// name: "DefaultApi",
// routeTemplate: "api/{controller}/{id}",
// defaults: new { id = RouteParameter.Optional }
//);
}
}
}
3.添加控制器
在Controllers下,添加SuppliersController.cs,其代码(参照ProductsControllers.cs CRUD写法):
using ProductService.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
namespace ProductService.Controllers
{
public class SuppliersController : ODataController
{
EFContext db = new EFContext();
[EnableQuery]
public IQueryable Get()
{
return db.Suppliers;
}
[EnableQuery]
public SingleResult Get([FromODataUri] int key)
{
IQueryable result = db.Suppliers.Where(p => p.Id == key);
return SingleResult.Create(result);
}
public async Task Post(Supplier supplier)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Suppliers.Add(supplier);
await db.SaveChangesAsync();
return Created(supplier);
}
public async Task Patch([FromODataUri] int key, Delta supplier)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await db.Suppliers.FindAsync(key);
if (entity == null)
{
return NotFound();
}
supplier.Patch(entity);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!SupplierExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
public async Task Put([FromODataUri] int key, Supplier update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (key != update.Id)
{
return BadRequest();
}
db.Entry(update).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!SupplierExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(update);
}
public async Task Delete([FromODataUri] int key)
{
var supplier = await db.Suppliers.FindAsync(key);
if (supplier == null)
{
return NotFound();
}
db.Suppliers.Remove(supplier);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
private bool SupplierExists(int key)
{
return db.Suppliers.Any(p => p.Id == key);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
4.修改控制器
打开Controllers\ProductsController.cs,添加下面方法(根据产品获取其供应商):
//一个产品有一家供应商
//获取产品供应商
// GET /Products(1)/Supplier
[EnableQuery]
public SingleResult GetSupplier([FromODataUri] int key)
{
var result = db.Products.Where(m => m.Id == key).Select(m => m.Supplier);
return SingleResult.Create(result);
}
打开Controllers\SuppliersController.cs,添加下面方法(根据供应商获取其所有产品):
//导航属性可以返回一个集合。
//获取供应商的产品
// GET /Suppliers(1)/Products
[EnableQuery]
public IQueryable GetProducts([FromODataUri] int key)
{
return db.Suppliers.Where(m => m.Id.Equals(key)).SelectMany(m => m.Products);
}
新建Commons文件夹,在里面添加Helpers.cs类:
(若要查找供应商,我们需要 ID (或键),这是链接参数的一部分,写个帮助方法)
using Microsoft.OData.Core;
using Microsoft.OData.Core.UriParser;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Routing;
using System.Web.OData.Extensions;
using System.Web.OData.Routing;
namespace ProductService.Commons
{
public static class Helpers
{
public static TKey GetKeyFromUri(HttpRequestMessage request, Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
}
var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request);
string serviceRoot = urlHelper.CreateODataLink(request.ODataProperties().RouteName,
request.ODataProperties().PathHandler, new List());
var odataPath = request.ODataProperties().PathHandler.Parse(
request.ODataProperties().Model, serviceRoot, uri.LocalPath);
var keySegment = odataPath.Segments.OfType().FirstOrDefault();
if (keySegment == null)
{
throw new InvalidOperationException("The link does not contain a key.");
}
var value = ODataUriUtils.ConvertFromUriLiteral(keySegment.Value, ODataVersion.V4);
return (TKey)value;
}
}
}
创建实体间添加关系:
打开Controllers\ProductsController.cs,添加下面方法:
(解决产品和其供应商之间的引用的 URI:/Products(1)/Supplier/$ref)
[AcceptVerbs("POST", "PUT")]
public async Task CreateRef([FromODataUri] int key, string navigationProperty, [FromBody] Uri link)
{
var product = await db.Products.SingleOrDefaultAsync(p => p.Id == key);
if (product == null)
{
return NotFound();
}
switch (navigationProperty)
{
case "Supplier":
// Note: The code for GetKeyFromUri is shown later in this topic.
var relatedKey = Helpers.GetKeyFromUriint>(Request, link);
var supplier = await db.Suppliers.SingleOrDefaultAsync(f => f.Id == relatedKey);
if (supplier == null)
{
return NotFound();
}
product.Supplier = supplier;
break;
default:
return StatusCode(HttpStatusCode.NotImplemented);
}
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
NavigationProperty参数指定要设置的关系。(如果在实体上有不止一个导航属性,你可以添加更多的case
声明)。
链接参数包含供应商的 URI。Web API 自动解析请求正文来获取此参数的值。
删除实体间关系(DELETE http://host/Products(1)/Supplier/$ref):
打开Controllers\ProductsController.cs,添加下面方法(删除一个产品和供应商之间的关系):
public async Task DeleteRef(
[FromODataUri] int key, string navigationProperty, [FromBody] Uri link)
{
var product = db.Products.SingleOrDefault(p => p.Id == key);
if (product == null)
{
return NotFound();
}
switch (navigationProperty)
{
case "Supplier":
product.Supplier = null;
break;
default:
return StatusCode(HttpStatusCode.NotImplemented);
}
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
打开Controllers\SuppliersController.cs,添加下面方法
public async Task DeleteRef([FromODataUri] int key,
[FromODataUri] string relatedKey, string navigationProperty)
{
var supplier = await db.Suppliers.SingleOrDefaultAsync(p => p.Id == key);
if (supplier == null)
{
return StatusCode(HttpStatusCode.NotFound);
}
switch (navigationProperty)
{
case "Products":
var productId = Convert.ToInt32(relatedKey);
var product = await db.Products.SingleOrDefaultAsync(p => p.Id == productId);
if (product == null)
{
return NotFound();
}
product.Supplier = null;
break;
default:
return StatusCode(HttpStatusCode.NotImplemented);
}
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}
WebApi学习笔记09:OData中的实体关系
标签:style blog http io color ar os for sp
原文地址:http://www.cnblogs.com/elder/p/4078075.html