博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转]Composite Keys With WebApi OData
阅读量:5160 次
发布时间:2019-06-13

本文共 4025 字,大约阅读时间需要 13 分钟。

本文转自:

In our basic configuration we told the model builder that our entity has a composite key comprised of an ID and a version:

123456 7 8 9 10
public void MapDataServiceRoutes(HttpConfiguration config) { var builder = new ODataConventionModelBuilder(); var entity = builder.EntitySet
("Packages"); entity.EntityType.HasKey(pkg => pkg.Id); entity.EntityType.HasKey(pkg => pkg.Version); // snip }

This is enough for our OData feed to render edit and self links for each individual entity in a form like:

http://localhost/odata/Packages(Id='Sample',Version='1.0.0')

But if we navigate to this URL, instead of getting just this one entity by key, we get back the entire entity set.

To get the correct behavior, first we need an override on our PackagesODataController that gets an individual entity instance by key:

123456 7 8 9 10 11 12 13 14 15 16 17 18 19 20
public class PackagesODataController : ODataController { public IMirroringPackageRepository Repository { get; set; } public IQueryable
Get() { return Repository.GetPackages().Select(p => p.ToODataPackage()).AsQueryable(); } public IHttpActionResult Get( [FromODataUri] string id, [FromODataUri] string version) { var package = Repository.FindPackage(id, version); return package == null ? (IHttpActionResult)NotFound() : Ok(package.ToODataPackage()); } }

However, out of the box WebApi OData doesn’t know how to bind composite key parameters to an action such as this, since the key is comprised of multiple values.

We can fix this by creating a new routing convention that binds the stuff inside the parenthesis to our route data map:

123456 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
public class CompositeKeyRoutingConvention : IODataRoutingConvention { private readonly EntityRoutingConvention entityRoutingConvention = new EntityRoutingConvention(); public virtual string SelectController( ODataPath odataPath, HttpRequestMessage request) { return entityRoutingConvention .SelectController(odataPath, request); } public virtual string SelectAction( ODataPath odataPath, HttpControllerContext controllerContext, ILookup
actionMap) { var action = entityRoutingConvention .SelectAction(odataPath, controllerContext, actionMap); if (action == null) { return null; } var routeValues = controllerContext.RouteData.Values; object value; if (!routeValues.TryGetValue(ODataRouteConstants.Key, out value)) { return action; } var compoundKeyPairs = ((string)value).Split(','); if (!compoundKeyPairs.Any()) { return null; } var keyValues = compoundKeyPairs .Select(kv => kv.Split('=')) .Select(kv => new KeyValuePair
(kv[0], kv[1])); routeValues.AddRange(keyValues); return action; } }

This class decorates a standard EntityRoutingConvention and splits the raw key portion of the URI into key/value pairs and adds them all to the routeValues dictionary.

Once this is done the standard action resolution kicks in and finds the correct action overload to invoke.

This routing convention was adapted from the WebApi project.

Here we see another difference between WebApi OData and WCF Data Services. In WCF Data Services, the framework handles generating a query that selects a single instance from an IQueryable. This limits our ability to customize how finding an instance by key is done. In WebApi OData, we have to explicitly define an overload that gets an entity instance by key, giving us more control over how the query is executed.

This distinction might not matter for most projects, but in the case of , it enables a mirror-on-demand capability where a local feed can fetch a package from another server on the fly, add it to the local repository, then send it back to the client as if it was always there in the first place.

To customize this in WCF Data Services required significant  .

 

Series Index

 

转载于:https://www.cnblogs.com/freeliver54/p/6934298.html

你可能感兴趣的文章
android网络通讯数据封装之 json
查看>>
Android 获取imageview的图,在另一个imageview里显示。
查看>>
android ExpandableListView
查看>>
Android Canvas使用drawBitmap绘制图片
查看>>
简单说-自定义cell
查看>>
sql 数据库(表空间),用户 相关命令
查看>>
C++数据类型
查看>>
模拟死锁
查看>>
【备忘录】flatten
查看>>
创建 VXLAN - 每天5分钟玩转 OpenStack(111)
查看>>
数据表与简单java类(角色与权限)
查看>>
MVC学习四:Razor视图语法
查看>>
Java 如何判断导入表格某列是否有重复数据
查看>>
selenium用法
查看>>
壳的执行过程
查看>>
ReentrantReadWriteLock类和ReentrantLock类的区别
查看>>
Qt5.3.2_CentOS6.4_基本编程环境__20160306【勿删,繁琐】
查看>>
Qt数据库_资料
查看>>
13.模块(概念)
查看>>
php实现获取汉字的首字母实例
查看>>