mars
2010
Entity Framework (dans sa version 3.5) permet d’exploiter des procédures stoquées afin de disposer de comportements particuliers.
Exemple : nous désirons supprimer des objets en cascade (suppression d’une commande, qui implique la suppression des lignes de commandes, qui implique …).
Cette suppression sera plus rapide si son exécution est confiée au moteur de base de données, plutôt que par des appels multiples sur un contexte EF.
D’où la création d’une procédure stoquée, et son intégration au sein d’EF.
Lorsque l’on désire exploiter les procédures stoquées au sein d’EF, il suffit de passer par une "Function Imports" mappée sur la procédure référencée au préalable dans EF.
Si cette dernière un objet déjà exploité par EF, aucun problème : la méthode liée à la procédure est dynamiquement générée dans le contexte EF lors de la création de la fonction EF.
Par contre, lorsqu’il s’agit de retourner un type simple ou void
: la méthode n’est pas générée…
Dans ce cas de figure, il faut donc "mettre les mains dans le moteur".
Pour ce faire, voici les étapes :
- Créez votre procédure stoquée (qui ne retourne rien…),
- Dans Visual Studio, ouvrez l’edmx, et sur le schéma, cliquez droit (menu contextuel), sélectionnez "Update Model From database" (voir ci dessous)
- Dans l’écran de synchronisation du modèle Entity Framework, déployez Stored Procedure et sélectionnez celle à "injecter" comme fonction dans Entity Framework, et validez…
- Ouvrez le Model Browser, et dans la partie qui concerne la description de la base de données utilisée par EF, déployez Store Procedure. Click droit sur celle qui nous intéresse et sélectionnez "Create Function Import"
(ce qui est grisé est le nom du datamodel du projet) - Cela entraine l’ouverture de l’écran de paramétrage de la fonction.
Ecran dans lequel, nous pouvons ajouter des précisions concernant la fonction (donc son nom).Passé ce stade ci, si le type de retour avait été Entity (un objet géré par EF), il aurait généré le code permettant l’appel de la fonction.
Pour vérifier qu’il a bien enregistré la fonction : ouvrez le Model Browser, et déployer la partie entity jusqu’aux fonctions :
- Créez une classe partielle portant le même nom, et même namespace que le contexte entity de votre modèle de données.
PS : Pour connaitre le nom de la classe :
- ouvrez l’edmx
- cliquez sur l’arrière plan
- F4 pour ouvrir l’écran de propriétés
- reprenez le nom de la propriété "Entity Container Name"
Re-PS : Pour connaitre le chemin du namespace de la classe :
Ouvrez le fichier .cs lié à l’edmx, et copiez le namespace en tête de fichier.Maintenant que vous disposez du nom complet de la classe (namespace + nom de classe), vous pouvez créer une classe qui va porter le même nom, même namespace, mais avec le mot clé partial.
  <br />
1: namespace MonNamespaceEF
2: {
3: using System;
4: using System.Collections.Generic;
5: using System.Linq;
6: using System.Text;
7:
8: public partial class MainDataModel
9: {
10: }
11: }
- Dernière étape : le code permettant d’exploiter EF par "l’intérieur".
Avant de montrer le code, une petite explication.
Entity Framework est une couche de type DAL (couche permettant les accès aux données + le mapping relationnel objet).
Étant donné qu’EF est conçu pour pouvoir fonctionner sur plusieurs sources de données (SQL Server, ou autre), il offre à l’utilisateur ses propres implémentations de DbConnection, DbCommand, etc afin de garder cette indépendance.
Donc, dans le code exposé ci dessous, nous n’utilisons ni d’OleDb, ni de SQLClient mais bien EntityConnection, EntityCommand, etc.1: namespace ClassLibrary1
2: {
3: using System;
4: using System.Collections.Generic;
5: using System.Linq;
6: using System.Text;
7: using System.Data.EntityClient;
8:
9: public partial class MainDataModel
10: {
11: /// <summary>
12: /// Supprime une machine en profondeur (impacte toutes les tables liées)
13: /// </summary>
14: /// <param name="idGamme">The id gamme.</param>
15: public void DeleteMachineDeep(String codeMachine)
16: {
17: // Crée une connection à partir de la cnnStr du datacontext
18: using (EntityConnection conn = new EntityConnection(this.Connection.ConnectionString))
19: {
20: try
21: {
22: EntityCommand cmd = conn.CreateCommand(); // crée une EntityCommand
23:
24: // CommandText correspond au nom de la fonction d'import (au sens Entity)
25: // le format d'identification est 'ContainerName.Stored Proc Name'
26: cmd.CommandText = String.Format("{0}.{1}", this.DefaultContainerName, "SUPPR_MACHINE");
27:
28: cmd.CommandType = System.Data.CommandType.StoredProcedure;
29: cmd.Parameters.AddWithValue("codeMachine", codeMachine); // ajout du param
30:
31: conn.Open();
32:
33: cmd.ExecuteNonQuery();
34: }
35: catch (Exception)
36: {
37: conn.Close();
38: throw; // renvoi l'exception pour traitement,
39: }
40: }
41: }
42: }
43: }
- L’utilisation :
1: ...
2: var dataCtx = new MainDataModel();
3: dataCtx.DeleteMachineDeep("ST1236");
4: ...
Avant de conclure, je souhaite revenir sur un point important : le fait qu’EF utilise des types d’objets de manipulation de source de données indépendant des implémentations réelle (EntityCommand, EntityConnection, etc) prouve qu’il a été conçu pour être exploité de façon indépendante du type de moteur de base de données sur lequel il s’appuie (et ce proprement).
@+