在ASP.NET Web API中使用OData的单例模式
从OData v4开始增加了对单例模式的支持,我们不用每次根据主键等来获取某个EDM,就像在C#中使用单例模式一样。实现方式大致需要两步:
1、在需要实现单例模式的导航属性上加上[Singleton]特性
2、在EDM配置的时候使用builder.Singleton<SomeModel>("SomeModels")来创建SingletonConfiguration<SomeModel>
首先还是从模型开始。
public class Employee
{
public int ID { get; set; }
public string Name { get; set; } [Singleton]
public Company Company { get; set; }
} public enum CompanyCategory
{
IT = ,
Communication = ,
Electronics = ,
Others =
} public class Company
{
public int ID { get; set; }
public string Name { get; set; }
public Int64 Revenue { get; set; }
public CompanyCategory Category { get; set; }
public List<Employee> Employees { get; set; }
}
以上,Company和Employee存在1对多关系,我们在Employee的Compnay导航属性上加上了[Singleton]特性,也就意味着我们希望在Company上使用单例模式。
然后就在WebApiConfig中配置如下:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
... config.MapODataServiceRoute("ODataRoute", "odata", GetEdmModel());
} public static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); EntitySetConfiguration<Employee> employeesConfiguration = builder.EntitySet<Employee>("Employees");
EntityTypeConfiguration<Employee> employeeTypeConfiguration = employeesConfiguration.EntityType;
employeeTypeConfiguration.Action("ResetDataSource"); SingletonConfiguration<Company> companiesConfiguration = builder.Singleton<Company>("Umbrella");
companiesConfiguration.EntityType.Action("ResetDataSource");
companiesConfiguration.EntityType.Function("GetEmployeesCount").Returns<int>(); builder.Namespace = "Hello"; return builder.GetEdmModel();
}
}
以上,builder.Singleton<Company>("Umbrella")方法创建SingletonConfiguration<Company>类型的实例,这是EDM实现单例的方式。
Company对应的控制器UmbrellaController
再来看Company对应的控制器,大致如下:
public class UmbrellaController : ODataController
{
public static Company Umbrella; static UmbrellaController()
{
InitData();
} private static void InitData()
{
Umbrella = new Company()
{
ID = ,
Name = "Umbrella",
Revenue = ,
Category = CompanyCategory.Communication,
Employees = new List<Employee>()
};
} ... [HttpPost]
public IHttpActionResult ResetDataSourceOnCompany()
{
InitData();
return StatusCode(HttpStatusCode.NoContent);
} public IHttpActionResult GetEmployeesCount()
{
return Ok(Umbrella.Employees.Count);
}
}
以上,UmbrellaController提供的静态Company类型的Umbrella可以在全局获取。ResetDataSourceOnCompany对应配置单例EDM的companiesConfiguration.EntityType.Action("ResetDataSource")的Action,GetEmployeesCount对应配置单例EDM的companiesConfiguration.EntityType.Function("GetEmployeesCount").Returns<int>()的Function。
● 查询
[EnableQuery]
public IHttpActionResult Get()
{
return Ok(Umbrella);
} public IHttpActionResult GetRevenueFromCompany()
{
return Ok(Umbrella.Revenue);
} public IHttpActionResult GetName()
{
return Ok(Umbrella.Employees);
}
以上,GetRevenueFromCompany和GetName分别获取属性,要符合惯例,即"Get+属性名称"。
● 添加
public IHttpActionResult Put(Company newCompany)
{
Umbrella = newCompany;
return StatusCode(HttpStatusCode.NoContent);
}
● Patch
public IHttpActionResult Patch(Delta<Company> item)
{
item.Patch(Umbrella);
return StatusCode(HttpStatusCode.NoContent);
}
● 创建Company上的Employees关系
/// <summary>
/// 创建Company上Employees的关系
/// </summary>
/// <param name="navigationProperty"></param>
/// <param name="link">Empolyee的uri地址</param>
/// <returns></returns>
[AcceptVerbs("POST")]
public IHttpActionResult CreateRef(string navigationProperty, [FromBody] Uri link)
{
//获取Employee的外键
int employeeId = HelperFunction.GetKeyValue<int>(link);
Employee employee = EmployeesController.Employees.First(x => x.ID == employeeId); if(employee == null || navigationProperty!="Employees")
{
return BadRequest();
} if(Umbrella.Employees == null)
{
Umbrella.Employees = new List<Employee>() { employee};
}
else
{
Umbrella.Employees.Add(employee);
}
return StatusCode(HttpStatusCode.NoContent);
}
其实就是往Company的Employees集合导航属性中添加一个元素。其中,HelperFunction.GetKeyValue<int>()方法用来获取link中Empoyee的主键。如下:
public static class HelperFunction
{
//获取主键值
public static TKey GetKeyValue<TKey>(Uri uri)
{
if(uri ==null)
{
throw new ArgumentException("uri");
} var rootPath = uri.AbsoluteUri.Substring(, uri.AbsoluteUri.LastIndexOf('/') + );
var odataUriParser = new ODataUriParser(WebApiConfig.GetEdmModel(), new Uri(rootPath), uri);
var odataPath = odataUriParser.ParsePath();
var keySegment = odataPath.LastSegment as KeySegment;
if(keySegment==null)
{
throw new InvalidOperationException("The link does not contain a key");
}
return (TKey)keySegment.Keys.First().Value;
}
}
● 删除Company上的Employees关系
/// <summary>
/// 删除关系
/// </summary>
/// <param name="relatedKey">Employee的主键</param>
/// <param name="navigationProperty"></param>
/// <returns></returns>
public IHttpActionResult DeleteRef(string relatedKey, string navigationProperty)
{
int key = int.Parse(relatedKey);
Employee employee = Umbrella.Employees.First(x => x.ID == key); if(navigationProperty != "Employees")
{
return BadRequest();
} Umbrella.Employees.Remove(employee);
return StatusCode(HttpStatusCode.NoContent);
}
其实就是删除Company的集合属性Employees中的一个Employee元素。
● 往Company的Employees集合里添加一个Employee元素
/// <summary>
/// 从Compnay处添加某个Employee
/// </summary>
/// <param name="employee"></param>
/// <returns></returns>
[HttpPost]
public IHttpActionResult PostToEmployees([FromBody] Employee employee)
{
EmployeesController.Employees.Add(employee);
if(Umbrella.Employees == null)
{
Umbrella.Employees = new List<Employee>() { employee };
}
else
{
Umbrella.Employees.Add(employee);
}
return Created(employee);
}
EmployeesController不详诉
public class EmployeesController : ODataController
{
public static List<Employee> Employees; static EmployeesController()
{
InitData();
} private static void InitData()
{
Employees = Enumerable.Range(, ).Select(i =>
new Employee()
{
ID = i,
Name = string.Format("Name {0}", i)
}).ToList();
} [EnableQuery]
public IHttpActionResult Get()
{
return Ok(Employees.AsQueryable());
} [EnableQuery]
public IHttpActionResult Get(int key)
{
return Ok(Employees.Where(e => e.ID == key));
} public IHttpActionResult GetCompanyFromEmployee([FromODataUri] int key)
{
var company = Employees.First(e => e.ID == key).Company;
if(company==null)
{
return StatusCode(HttpStatusCode.NotFound);
}
return Ok(company);
} public IHttpActionResult Post([FromBody] Employee employee)
{
Employees.Add(employee);
return Created(employee);
} [AcceptVerbs("PUT")]
public IHttpActionResult CreateRef([FromODataUri] int key, string navigationProperty, [FromBody] Uri link)
{
if(navigationProperty!="Company")
{
return BadRequest();
}
Employees.First(e => e.ID == key).Company = UmbrellaController.Umbrella;
return StatusCode(HttpStatusCode.NoContent); } public IHttpActionResult DeleteRef([FromODataUri] int key, string navigationProperty)
{
if(navigationProperty!="Company")
{
return BadRequest();
} Employees.First(e => e.ID == key).Company = null;
return StatusCode(HttpStatusCode.NoContent);
} public IHttpActionResult PutToCompany(int key, Company company)
{
var navigateCompany = Employees.First(e => e.ID == key).Company;
Employees.First(e => e.ID == key).Company = company;
if(navigateCompany.Name == "Umbrella")
{
//体现Singleton
UmbrellaController.Umbrella = navigateCompany;
}
else
{
return BadRequest();
}
return StatusCode(HttpStatusCode.NoContent);
} public IHttpActionResult PatchToCompany(int key, Delta<Company> company)
{
var navigateCompan = Employees.First(e => e.ID == key).Company;
company.Patch(Employees.First(e => e.ID == key).Company); if(navigateCompan.Name == "Umbrella")
{
company.Patch(UmbrellaController.Umbrella);
}
else
{
return BadRequest();
}
return StatusCode(HttpStatusCode.NoContent);
} [HttpPost]
public IHttpActionResult ResetDataSourceOnCollectionOfEmployee()
{
InitData();
return Ok();
}
}
在ASP.NET Web API中使用OData的单例模式的更多相关文章
- ASP.NET Web API中使用OData
在ASP.NET Web API中使用OData 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在ASP.NET Web API中,对于CRUD(creat ...
- 在ASP.NET Web API中使用OData
http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...
- 在ASP.NET Web API中使用OData的Action和Function
本篇体验OData的Action和Function功能.上下文信息参考"ASP.NET Web API基于OData的增删改查,以及处理实体间关系".在本文之前,我存在的疑惑包括: ...
- [翻译]在ASP.NET Web API中通过OData支持查询和分页
OData可以通过形如http://localhost/Products?$orderby=Name这样的QueryString传递查询条件.排序等.你可以在任何Web API Controller中 ...
- 在ASP.NET Web API中使用OData的Containment
通常情况下,一个OData的EDM(Entity Data Model)在配置的时候定义了,才可以被查询或执行各种操作.比如如下: builder.EntitySet<SomeModel> ...
- ASP.NET Web API中的Controller
虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...
- ASP.NET Web API 中的异常处理(转载)
转载地址:ASP.NET Web API 中的异常处理
- 【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化
谨以此文感谢关注此系列文章的园友!前段时间本以为此系列文章已没多少人关注,而不打算继续下去了.因为文章贴出来之后,看的人似乎不多,也很少有人对这些文章发表评论,而且几乎无人给予“推荐”.但前几天有人询 ...
- Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...
随机推荐
- slf4j MDC使用
slf4j MDC使用 最近也是在项目代码里发现一个地方有个MDC.put(),忍不住好奇点了进去,于是知道了MDC这个东西,细研究一下,发现还真是个好东西. MDC解决了什么问题 MDC全名Mapp ...
- Linux Timer定时器【转】
转自:https://www.jianshu.com/p/66b3c75cae81 timerfd为Linux为用户程序提供的定时器接口,该接口基于文件描述符,通过文件描述符的可读事件进行超时通知,且 ...
- 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集【转】
转自:http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一直想把USB摄像头接到Zedboard上,搭建 ...
- IDEA配置文件的配置文件配置
IDEA配置文件的配置文件配置: 路径 /Applications/IntelliJ IDEA 3.app/Contents/bin/idea.vmoptions (/IntelliJ IDEA 3. ...
- jenkins免密添加SSH Servers
在配置ssh server时可以使用用户名秘密的方式登录,但有点不安全,只要有权限配置jenkins服务器的人就可以看到密码.所以可以利用ssh免密登录的方式链接ssh server. 1.在jenk ...
- opencv 车牌字符分割 ANN网络识别字符
最近在复习OPENCV的知识,学习caffe的深度神经网络,正好想起以前做过的车牌识别项目,可以拿出来研究下 以前的环境是VS2013和OpenCV2.4.9,感觉OpenCV2.4.9是个经典版本啊 ...
- vscodes使用(一): 常用插件,在线与离线安装
一.常用插件 1.Live server 浏览器实时刷新 插件安装成功后,会在底部工具栏中,显示个Go Live *.html文件,点击右键,可以看到live server两条指令 2.Esasy ...
- Vue开源
Vue开源 - 为移动而生的Vue JS 2组件框架 vonic ★1494 - 快速构建移动端单页应用 eme ★1390 - 优雅的Markdown编辑器 vue-multiselect ★116 ...
- nginx静态资源缓存策略配置
1. 问题-背景 以前也经常用nginx,但用的不深,通常是简单的设置个location用来做反向代理.直到今天给客户做项目碰到缓存问题:客户有个app,只是用原生做了个壳,里面的内容都是用h5写的, ...
- P1091 合唱队形 DP 最长升序列维护
题目描述 NN位同学站成一排,音乐老师要请其中的(N-KN−K)位同学出列,使得剩下的KK位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K,他 ...