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.


Voir également