EF : SELECT avec une SP
Imaginons que l'on ait une procédure stockée qui fait juste un SELECT et que l'on veuille l'intégrer dans notre EDM. Pour cela, on va créer un entity type. Maintenant imposons une contrainte : il faut forcément passer par la procédure stockée pour récupérer des instances de notre entity type.
Ce scenario n'est pas vraiment prévu par la V1 de l'Entity Framework et de "bidouiller" un peu.
Imaginons la procédure stockée suivante :
CREATE PROCEDURE [dbo].[TOTO]
AS
BEGIN
SELECT Id, 1 AS VALUE FROM Test
END
Quand on va récupérer notre procédure stockée dans notre EDM, on va avoir l'info dans le SSDL :
<Function Name="TOTO" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" />
Ensuite, il faut créer l'entity type dans le CSDL (ce que l'on peut faire avec le designer) :
<EntityType Name="Toto">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Int32" Nullable="false" />
<Property Name="Value" Type="Int32" Nullable="true" />
</EntityType>
Avec la création de l'entity type, on va également avoir un EntitySet :
<EntitySet Name="Totos" EntityType="TestModel.Toto" />
Ensuite, on peut ajouter un "Function Import" dans le CSDL, ce qui aura pour effet de rajouter une méthode à notre ObjectContext qui appellera notre procédure stockée. Il suffit de lui préciser lors de l'ajout de "Function Import" que le type de retour est Toto.
Attention, il faut que les propriétés de Toto aient le même nom que les colonnes retournées par notre procédure stockée.
Ensuite, comme on ne veut pas de l'EntitySet sur notre ObjectContext (car on veut obligatoirement passé via la proc stock), on va le passer en private. A noter, qu'il est possible de le faire via le designer en allant sur la fenêtre Model Browser, puis en déroulant le noeud EntityContainer puis EntitySets puis en allant sur le noeud Totos, en allant ensuite dans la fenêtre Properties et en modifiant la visibilité du Getter.
On pourrait penser que c'est bon mais non ! En effet, il faut obligatoirement mapper l'entity type Toto (même si dans notre cas ça ne sert à rien).
Comment faire ?
Avec une SSDL View.
Vu qu'elle ne sera pas utilisée, on peut mettre n'importe quoi comme commande SQL :
<EntityContainer Name="TestModelStoreContainer">
<EntitySet Name="Totos" EntityType="TestModel.Store.Toto" >
<DefiningQuery>
SELECT 1
</DefiningQuery>
</EntitySet>
</EntityContainer>
<EntityType Name="Toto">
<Key>
<PropertyRef Name="Id"/>
</Key>
<Property Name="Id" Type="int" Nullable="false"/>
<Property Name="Value" Type="int" />
</EntityType>
et ensuite mapper l'entity type sur notre SSDL View.
Pour la V2, ce scenario sera réellement supporté comme me l'a confirmé Daniel Simmons : "In v2 we’re allowing sprocs to return complex types which will be the easy way to return objects which don’t need to be mapped, etc."
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :