[Entity Framewok 4] Accélérer le temps de chargement d’Entity Framework 4 avec EFCachingProvider en ASP.NET

Comme vu précédemment dans l’article : Reduire le temps de chargement d’une page ASP.NET avec le SQL Cache Dependency, il est possible de réduire le temps de chargement d’une page en mettant en cache les résultats récupérés dans la base de données.

 

L’article précédent traité du SQL Cache Dependency avec Linq To SQL. Avec Entity Framework 4, cette méthode n’est pas disponible, il faut donc se rabattre sur un provider personnalisé créé par Jaroslaw Kowalski : EFCachingProvider.

 

Comme expliqué sur la page MSDN du provider, Entity Framework 4 permet l’ajout de providers personnalisés afin de supporter d’autres types de base de données comme Oracle, MySQL, etc… Cette possibilité permet également de rajouter une couche de cache, log, sécurité, etc… c’est le cas ici pour la cache. Pour plus de détails consulter la page MSDN mentionnée ci-dessus.

 

Utilisation de EFCachingProvider

 

Prérequis : Avoir un projet ASP.NET contenant un fichier .edmx correctement configuré.

– Commencez par télécharger les fichiers DLL des providers : ici.

– Ajoutez les fichiers DLL à votre projet et ajoutez les références vers ces DLL dans votre projet.

– Ouvrez le fichier web.config et ajoutez les lignes suivantes afin d’enregistrer les providers :

 

<system.data>
  <DbProviderFactories>
    <add name="EF Caching Data Provider"
    invariant="EFCachingProvider"
    description="Caching Provider Wrapper"
    type="EFCachingProvider.EFCachingProviderFactory, EFCachingProvider, 
Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
    <add name="EF Generic Provider Wrapper"
    invariant="EFProviderWrapper"
    description="Generic Provider Wrapper"
    type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit, 
Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
  </DbProviderFactories>
</system.data>

 

– Ajoutez (si ce n’est pas déjà le cas) un fichier Global.asax. Dans la méthode Application_Start, ajoutez les lignes suivantes :

 

EFCachingProviderConfiguration.DefaultCache = new AspNetCache();
EFCachingProviderConfiguration.DefaultCachingPolicy = CachingPolicy.CacheAll;

 

– Créer une classe ExtendedEntities qui hérite de la classe générée par Entity Framework 4 avec le .edmx (ici EFCachingEntities) :

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EFCachingProvider;
using EFCachingProvider.Caching;
using EFProviderWrapperToolkit;

namespace EFCaching
{
    public class ExtendedEntities : EFCachingEntities
    {
        public ExtendedEntities()
            : this("name=EFCachingEntities")
        {
        }

        public ExtendedEntities(string connectionString)
            : base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
            connectionString,
            "EFCachingProvider"
            ))
        {
        }

        private EFCachingConnection CachingConnection
        {
            get { return this.UnwrapConnection<EFCachingConnection>(); }
        }

        public ICache Cache
        {
            get { return CachingConnection.Cache; }
            set { CachingConnection.Cache = value; }
        }

        public CachingPolicy CachingPolicy
        {
            get { return CachingConnection.CachingPolicy; }
            set { CachingConnection.CachingPolicy = value; }
        }
    }
}

 

A la ligne 14, n’oubliez pas de remplacer EFCachingEntities par votre chaine de connexion.

Tout est désormais prêt pour utiliser le système de cache. Ci-dessous, le code avec et sans l’utilisation du provider :

 

Avec EFCachingProvider

 

protected void Page_Load(object sender, EventArgs e)
{
    using (ExtendedEntities ent = new ExtendedEntities())
    {
        List<Ville> villes = (from v in ent.Villes select v).ToList();
    }
}

 

Sans EFCachingProvider

 

protected void Page_Load(object sender, EventArgs e)
{
    using (EFCachingEntities ent = new EFCachingEntities())
    {
        List<Ville> villes = (from v in ent.Villes select v).ToList();
    }
}

 

Notez que seule la ligne 3 change avec l’utilisation de ExtendedEntities à la place de EFCachingEntities.

Performances

Concernant mes tests, j’ai utilisé la base de données contenant toutes les villes françaises soit 34487 lignes.

 

Sur 10 essais, sans la couche EFCachingProvider, le temps de chargement moyen est de 0,5978s. Avec EFCachingProvider ce temps dessend à 0,3301s soit un temps de chargement divisé par 1,8.

 

Il est possible de télécharger ici le projet utilisé pour les tests.

[Entity Framework 4] Utiliser des procédures stockées avec Entity Framework 4

Pour des raisons de sécurité et de performance, il peut être judicieux d’utiliser des procédures stockées pour interagir avec la base de données. Cet article a pour but de démontrer comment utiliser les procédures stockées avec le framework Entity 4.

Le but de l’article est de créer 4 procédures stockées pour ajouter, modifier et récupérer des blogs dans la base de données :

 

  • Insert(nvarchar(max) name, nvarchar(max) url)

Pour ajouter un blog dans la base de données. Elle retourne l’ID du blog qui vient dêtre ajouté.

 

CREATE PROCEDURE [dbo].[Insert]
(
@name nvarchar(max),
@url nvarchar(max)
)
AS

INSERT INTO [dbo].[Blogs]
(name, url)
VALUES
(@name, @url);

SELECT CONVERT(int, SCOPE_IDENTITY());

 

Note : Pour retourner l’ID généré lors de l’INSERT, il faut utiliser SELECT et non RETURN.

 

  • Update(int id, nvarchar(max) name, nvarchar(max) url)

Pour modifier un blog déjà présent dans la base de données. La procédure retourne le nombre de lignes modifiées.

 

CREATE PROCEDURE [dbo].[Update]
(
@id int,
@name nvarchar(max),
@url nvarchar(max)
)
AS

UPDATE [dbo].[Blogs] SET
name = @name,
url = @url
WHERE id = @id;

 

  • GetAll()

Récupère tous les blogs de la base de données. Elle retourne une liste d’objets de type Blog.

 

CREATE PROCEDURE [dbo].[GetAll]
AS
SELECT * FROM [dbo].[Blogs];

 

  • GetByID(int id)

Récupère le blog correspondant à l’ID passé en paramètre. La procédure renvoie un objet de type Blog.

 

CREATE PROCEDURE [dbo].[GetByID]
(
@id int
)
AS

SELECT * FROM [dbo].[Blogs]
WHERE id = @id;

 

La table Blogs est la suivante :

 

 

Pour commencer, il faut ajouter un fichier .edmx au projet afin de faire la liaison entre l’application et la base de données

 

 

La génération du fichier .edmx se fait automatiquement depuis la base de données.

 

 

Sélection de la table blog et des procédures stockées.

 

 

Il faut maintenant importer une par une les procédures stockées via le menu Model Browser.

 

 

Répéter l’opération pour les 4 procédures stockées en prêtant attention au type de retour :

 

  • Pour Insert, la procédure renvoie l’ID nouvellement créé, il faut donc retourner une collection d’objets de type scalaire Int32.
  • Pour Update, la procédure renvoie le nombre de lignes modifiées. Tout est géré par EF4, le type de retour est donc none.
  • Pour GetAll, la procédure renvoie une collection d’objets de type Blog, il faut donc retourner une collection d’entités Blog.
  • Pour GetByID, la procédure renvoie un object de type Blog, il faut donc retourner une collection d’entités Blog.

Tout est maintenant en place pour interagir avec la base de données. Voici comment appeler les procédures stockées.

 

StoredProcedureEFArticleEntities ent = new StoredProcedureEFArticleEntities();

// Insert
int? idAymeric = ent.Insert("Aymeric's blog", "https://www.aymericlagier.com")
                    .FirstOrDefault();
int? idMSDN = ent.Insert("MSDN Fr", "http://msdn.microsoft.com/fr-fr/default.aspx")
                 .FirstOrDefault();
int? idJulienD = ent.Insert("Julien Dollon", "http://blogs.dotnet-france.com/juliend/")
                    .FirstOrDefault();

// Update
if (idMSDN.HasValue)
{
    ent.Update(idMSDN.Value, "MSDN US", "http://msdn.microsoft.com");
}

// GetByID
if (idAymeric.HasValue)
{
    Blog myBlog = ent.GetByID(idAymeric.Value).FirstOrDefault();
}

// GetAll
List<Blog> blogs = ent.GetAll().ToList();
 

Pour télécharger le projet relatif à l’article, cliquez ici.