在ASP.NET Web API中使用OData的单例模式
2015-11-10 10:44
567 查看
从OData v4开始增加了对单例模式的支持,我们不用每次根据主键等来获取某个EDM,就像在C#中使用单例模式一样。实现方式大致需要两步:
1、在需要实现单例模式的导航属性上加上[Singleton]特性
2、在EDM配置的时候使用builder.Singleton<SomeModel>("SomeModels")来创建SingletonConfiguration<SomeModel>
首先还是从模型开始。
以上,Company和Employee存在1对多关系,我们在Employee的Compnay导航属性上加上了[Singleton]特性,也就意味着我们希望在Company上使用单例模式。
然后就在WebApiConfig中配置如下:
以上,builder.Singleton<Company>("Umbrella")方法创建SingletonConfiguration<Company>类型的实例,这是EDM实现单例的方式。
[b]Company对应的控制器UmbrellaController[/b]
再来看Company对应的控制器,大致如下:
以上,UmbrellaController提供的静态Company类型的Umbrella可以在全局获取。ResetDataSourceOnCompany对应配置单例EDM的companiesConfiguration.EntityType.Action("ResetDataSource")的Action,GetEmployeesCount对应配置单例EDM的companiesConfiguration.EntityType.Function("GetEmployeesCount").Returns<int>()的Function。
● 查询
以上,GetRevenueFromCompany和GetName分别获取属性,要符合惯例,即"Get+属性名称"。
● 添加
● Patch
● 创建Company上的Employees关系
其实就是往Company的Employees集合导航属性中添加一个元素。其中,HelperFunction.GetKeyValue<int>()方法用来获取link中Empoyee的主键。如下:
● 删除Company上的Employees关系
其实就是删除Company的集合属性Employees中的一个Employee元素。
● 往Company的Employees集合里添加一个Employee元素
[b]EmployeesController不详诉[/b]
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 = 0, Communication = 1, Electronics = 2, Others = 3 } 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实现单例的方式。
[b]Company对应的控制器UmbrellaController[/b]
再来看Company对应的控制器,大致如下:
public class UmbrellaController : ODataController { public static Company Umbrella; static UmbrellaController() { InitData(); } private static void InitData() { Umbrella = new Company() { ID = 1, Name = "Umbrella", Revenue = 1000, 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(0, uri.AbsoluteUri.LastIndexOf('/') + 1); 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); }
[b]EmployeesController不详诉[/b]
public class EmployeesController : ODataController { public static List<Employee> Employees; static EmployeesController() { InitData(); } private static void InitData() { Employees = Enumerable.Range(0, 10).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(); } }
相关文章推荐
- 界面控件Essential Studio for ASP.NET正式发布2015 v3[附下载]
- SpringMVC与iReport(JasperReports) 5.6整合开发实例
- asp.net 字符串替换、截取和从字符串中最后某个字符 开始截取
- 在ASP.NET Web API中使用OData的Containment
- asp.net web常用控件FileUpload(文件上传控件)
- ASP.NET WebAPI 11 参数验证
- 关于js的加载顺序及Asp.net MVC中list问题
- Spring之—— AspectJ AOP 完整示例
- ASP.NET的几个试题(《C#与.NET程序员面试宝典》)
- ASP.NET多文件上传实例
- C#,Dictionary,asp.net 字典 用法及简单操作
- C#,Dictionary,asp.net 字典 用法及简单操作
- asp.net堆和栈的对比 #1
- asp.net试题解析
- Barcode Professional for ASP.NET使用教程:如何在HTML支持的DPI范围内显示高清条码
- Asp.Net 之 未能加载文件或程序集 system.web.extensions 解决方法
- Barcode Professional for ASP.NET使用教程:如何在HTML支持的DPI范围内显示高清条码
- ASP.NET中在不同的子域中共享Session(二级域名获取不到主域名下的session值)
- ASP.NET动态网站制作(26)-- Ajax
- ExtAspNet框架