本文转自:http://chris.eldredge.io/blog/2014/04/24/composite-keys/
In our basic configuration we told the model builder that our entity has a composite key comprised of an ID and a version:
<span class="line-number">1 <span class="line-number">2 <span class="line-number">3 <span class="line-number">4 <span class="line-number">5 <span class="line-number">6 <span class="line-number">7 <span class="line-number">8 <span class="line-number">9 <span class="line-number">10 </span></span></span></span></span></span></span></span></span></span> 登录后复制 |
<code class="c#"><span class="line"><span class="k">public <span class="k">void <span class="nf">MapDataServiceRoutes<span class="p">(<span class="n">HttpConfiguration <span class="n">config<span class="p">)
<span class="line"><span class="p">{
<span class="line"> <span class="kt">var <span class="n">builder <span class="p">= <span class="k">new <span class="n">ODataConventionModelBuilder<span class="p">();
<span class="line">
<span class="line"> <span class="kt">var <span class="n">entity <span class="p">= <span class="n">builder<span class="p">.<span class="n">EntitySet<span class="p"><<span class="n">ODataPackage<span class="p">>(<span class="s">"Packages"<span class="p">);
<span class="line"> <span class="n">entity<span class="p">.<span class="n">EntityType<span class="p">.<span class="n">HasKey<span class="p">(<span class="n">pkg <span class="p">=> <span class="n">pkg<span class="p">.<span class="n">Id<span class="p">);
<span class="line"> <span class="n">entity<span class="p">.<span class="n">EntityType<span class="p">.<span class="n">HasKey<span class="p">(<span class="n">pkg <span class="p">=> <span class="n">pkg<span class="p">.<span class="n">Version<span class="p">);
<span class="line">
<span class="line"> <span class="c1">// snip
<span class="line"><span class="p">}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>登录后复制 |
This is enough for our OData feed to render edit and self links for each individual entity in a form like:
<code>http://localhost/odata/Packages(Id='Sample',Version='1.0.0') </code>
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:
<span class="line-number">1 <span class="line-number">2 <span class="line-number">3 <span class="line-number">4 <span class="line-number">5 <span class="line-number">6 <span class="line-number">7 <span class="line-number">8 <span class="line-number">9 <span class="line-number">10 <span class="line-number">11 <span class="line-number">12 <span class="line-number">13 <span class="line-number">14 <span class="line-number">15 <span class="line-number">16 <span class="line-number">17 <span class="line-number">18 <span class="line-number">19 <span class="line-number">20 </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span> 登录后复制 |
<code class="c#"><span class="line"><span class="k">public <span class="k">class <span class="nc">PackagesODataController <span class="p">: <span class="n">ODataController
<span class="line"><span class="p">{
<span class="line"> <span class="k">public <span class="n">IMirroringPackageRepository <span class="n">Repository <span class="p">{ <span class="k">get<span class="p">; <span class="k">set<span class="p">; <span class="p">}
<span class="line">
<span class="line"> <span class="k">public <span class="n">IQueryable<span class="p"><<span class="n">ODataPackage<span class="p">> <span class="n">Get<span class="p">()
<span class="line"> <span class="p">{
<span class="line"> <span class="k">return <span class="n">Repository<span class="p">.<span class="n">GetPackages<span class="p">().<span class="n">Select<span class="p">(<span class="n">p <span class="p">=> <span class="n">p<span class="p">.<span class="n">ToODataPackage<span class="p">()).<span class="n">AsQueryable<span class="p">();
<span class="line"> <span class="p">}
<span class="line">
<span class="line"> <span class="k">public <span class="n">IHttpActionResult <span class="nf">Get<span class="p">(
<span class="line"><span class="na"> [FromODataUri] <span class="kt">string <span class="n">id<span class="p">,
<span class="line"><span class="na"> [FromODataUri] <span class="kt">string <span class="n">version<span class="p">)
<span class="line"> <span class="p">{
<span class="line"> <span class="kt">var <span class="n">package <span class="p">= <span class="n">Repository<span class="p">.<span class="n">FindPackage<span class="p">(<span class="n">id<span class="p">, <span class="n">version<span class="p">);
<span class="line">
<span class="line"> <span class="k">return <span class="n">package <span class="p">== <span class="k">null
<span class="line"> <span class="p">? <span class="p">(<span class="n">IHttpActionResult<span class="p">)<span class="n">NotFound<span class="p">()
<span class="line"> <span class="p">: <span class="n">Ok<span class="p">(<span class="n">package<span class="p">.<span class="n">ToODataPackage<span class="p">());
<span class="line"> <span class="p">}
<span class="line"><span class="p">}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>登录后复制 |
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:
<span class="line-number">1 <span class="line-number">2 <span class="line-number">3 <span class="line-number">4 <span class="line-number">5 <span class="line-number">6 <span class="line-number">7 <span class="line-number">8 <span class="line-number">9 <span class="line-number">10 <span class="line-number">11 <span class="line-number">12 <span class="line-number">13 <span class="line-number">14 <span class="line-number">15 <span class="line-number">16 <span class="line-number">17 <span class="line-number">18 <span class="line-number">19 <span class="line-number">20 <span class="line-number">21 <span class="line-number">22 <span class="line-number">23 <span class="line-number">24 <span class="line-number">25 <span class="line-number">26 <span class="line-number">27 <span class="line-number">28 <span class="line-number">29 <span class="line-number">30 <span class="line-number">31 <span class="line-number">32 <span class="line-number">33 <span class="line-number">34 <span class="line-number">35 <span class="line-number">36 <span class="line-number">37 <span class="line-number">38 <span class="line-number">39 <span class="line-number">40 <span class="line-number">41 <span class="line-number">42 <span class="line-number">43 <span class="line-number">44 <span class="line-number">45 <span class="line-number">46 <span class="line-number">47 <span class="line-number">48 <span class="line-number">49 <span class="line-number">50 <span class="line-number">51 <span class="line-number">52 </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span> 登录后复制 |
<code class="c#"><span class="line"><span class="k">public <span class="k">class <span class="nc">CompositeKeyRoutingConvention <span class="p">: <span class="n">IODataRoutingConvention
<span class="line"><span class="p">{
<span class="line"> <span class="k">private <span class="k">readonly <span class="n">EntityRoutingConvention <span class="n">entityRoutingConvention <span class="p">=
<span class="line"> <span class="k">new <span class="nf">EntityRoutingConvention<span class="p">();
<span class="line">
<span class="line"> <span class="k">public <span class="k">virtual <span class="kt">string <span class="nf">SelectController<span class="p">(
<span class="line"> <span class="n">ODataPath <span class="n">odataPath<span class="p">,
<span class="line"> <span class="n">HttpRequestMessage <span class="n">request<span class="p">)
<span class="line"> <span class="p">{
<span class="line"> <span class="k">return <span class="n">entityRoutingConvention
<span class="line"> <span class="p">.<span class="n">SelectController<span class="p">(<span class="n">odataPath<span class="p">, <span class="n">request<span class="p">);
<span class="line"> <span class="p">}
<span class="line">
<span class="line"> <span class="k">public <span class="k">virtual <span class="kt">string <span class="nf">SelectAction<span class="p">(
<span class="line"> <span class="n">ODataPath <span class="n">odataPath<span class="p">,
<span class="line"> <span class="n">HttpControllerContext <span class="n">controllerContext<span class="p">,
<span class="line"> <span class="n">ILookup<span class="p"><<span class="kt">string<span class="p">, <span class="n">HttpActionDescriptor<span class="p">> <span class="n">actionMap<span class="p">)
<span class="line"> <span class="p">{
<span class="line"> <span class="kt">var <span class="n">action <span class="p">= <span class="n">entityRoutingConvention
<span class="line"> <span class="p">.<span class="n">SelectAction<span class="p">(<span class="n">odataPath<span class="p">, <span class="n">controllerContext<span class="p">, <span class="n">actionMap<span class="p">);
<span class="line">
<span class="line"> <span class="k">if <span class="p">(<span class="n">action <span class="p">== <span class="k">null<span class="p">)
<span class="line"> <span class="p">{
<span class="line"> <span class="k">return <span class="k">null<span class="p">;
<span class="line"> <span class="p">}
<span class="line">
<span class="line"> <span class="kt">var <span class="n">routeValues <span class="p">= <span class="n">controllerContext<span class="p">.<span class="n">RouteData<span class="p">.<span class="n">Values<span class="p">;
<span class="line">
<span class="line"> <span class="kt">object <span class="k">value<span class="p">;
<span class="line"> <span class="k">if <span class="p">(!<span class="n">routeValues<span class="p">.<span class="n">TryGetValue<span class="p">(<span class="n">ODataRouteConstants<span class="p">.<span class="n">Key<span class="p">,
<span class="line"> <span class="k">out <span class="k">value<span class="p">))
<span class="line"> <span class="p">{
<span class="line"> <span class="k">return <span class="n">action<span class="p">;
<span class="line"> <span class="p">}
<span class="line">
<span class="line"> <span class="kt">var <span class="n">compoundKeyPairs <span class="p">= <span class="p">((<span class="kt">string<span class="p">)<span class="k">value<span class="p">).<span class="n">Split<span class="p">(<span class="sc">','<span class="p">);
<span class="line">
<span class="line"> <span class="k">if <span class="p">(!<span class="n">compoundKeyPairs<span class="p">.<span class="n">Any<span class="p">())
<span class="line"> <span class="p">{
<span class="line"> <span class="k">return <span class="k">null<span class="p">;
<span class="line"> <span class="p">}
<span class="line">
<span class="line"> <span class="kt">var <span class="n">keyValues <span class="p">= <span class="n">compoundKeyPairs
<span class="line"> <span class="p">.<span class="n">Select<span class="p">(<span class="n">kv <span class="p">=> <span class="n">kv<span class="p">.<span class="n">Split<span class="p">(<span class="sc">'='<span class="p">))
<span class="line"> <span class="p">.<span class="n">Select<span class="p">(<span class="n">kv <span class="p">=>
<span class="line"> <span class="k">new <span class="n">KeyValuePair<span class="p"><<span class="kt">string<span class="p">, <span class="kt">object<span class="p">>(<span class="n">kv<span class="p">[<span class="m">0<span class="p">], <span class="n">kv<span class="p">[<span class="m">1<span class="p">]));
<span class="line">
<span class="line"> <span class="n">routeValues<span class="p">.<span class="n">AddRange<span class="p">(<span class="n">keyValues<span class="p">);
<span class="line">
<span class="line"> <span class="k">return <span class="n">action<span class="p">;
<span class="line"> <span class="p">}
<span class="line"><span class="p">}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>登录后复制 |
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 ODataCompositeKeySampleproject.
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 NuGet.Lucene.Web, 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 back flips.
以上就是[转]Composite Keys With WebApi OData的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号