Maison  >  Article  >  développement back-end  >  Clés composites avec WebApi OData

Clés composites avec WebApi OData

PHP中文网
PHP中文网original
2017-06-17 16:34:011397parcourir

本文转自:http://chris.eldredge.io/blog/2014/04/24/Composite-Keys/

Dans notre configuration de base, nous avons indiqué au constructeur de modèles que notre entité possède une clé composite composée d'un identifiant et d'une 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">7879bc2b6ec581464773019d50856563(<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></code>

Cela suffit pour que notre flux OData affiche edit et self des liens pour chaque entité individuelle sous une forme telle que :

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

Mais si nous naviguons vers cette URL, au lieu d'obtenir uniquement cette entité par clé, nous récupérons l'ensemble de l'entité.

Pour obtenir le comportement correct, nous avons d'abord besoin d'un remplacement sur notre PackagesODataController qui obtient une instance d'entité individuelle par clé :

<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">7879bc2b6ec581464773019d50856563 <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></code>

Cependant, WebApi OData ne sait pas comment lier les paramètres de clé composite à une action comme celle-ci, car la clé est composée de plusieurs valeurs.

Nous pouvons résoudre ce problème en créant une nouvelle convention de routage qui lie les éléments entre parenthèses à notre carte de données d'itinéraire :

<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">9a25b537e4c6dcc50cba8604f85ed988 <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">0f7bec63ba201452c985b787f98f17b8(<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></code>

Cette classe décore un standard EntityRoutingConvention et divise la partie clé brute de l'URI en paires clé/valeur et les ajoute toutes au dictionnaire routeValues.

Une fois cela fait, la résolution d'action standard entre en jeu et trouve la surcharge d'action correcte à invoquer.

Cette convention de routage a été adaptée du projet WebApi ODataCompositeKeySample.

Nous voyons ici une autre différence entre WebApi OData et WCF Data Services. Dans WCF Data Services, le framework gère la génération d'une requête qui sélectionne une seule instance à partir d'un IQueryable. Cela limite notre capacité à personnaliser la façon dont la recherche d'une instance par clé est effectuée. Dans WebApi OData, nous devons définir explicitement une surcharge qui obtient une instance d'entité par clé, nous donnant plus de contrôle sur la façon dont la requête est exécutée.

Cette distinction n'a peut-être pas d'importance pour la plupart des projets, mais dans le cas de NuGet.Lucene.Web, elle permet une fonctionnalité de mise en miroir à la demande où un flux local peut récupérer un package à partir d'un autre serveur à la volée, l'ajouter à le référentiel local, puis renvoyez-le au client comme s'il était toujours là en premier lieu.

La personnalisation de cela dans WCF Data Services a nécessité d'importants retournements en arrière.

 

Index des séries

  1. Présentation
  2. WebApi OData de base
  3. Clés composites
  4. Flux par défaut

 

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn