Bonjour,
Le sujet de l'article d'aujourd'hui va être de discuter de Cache avec LinqToSql et Entreprise Library Caching Block.
J'ai repris l'exemple donné par J Sawyer qui a posté un article sur la mise en Cache des collections LinqToSql via la classe System.Web.Caching.
Ce que je vous proposer aujourd'hui c'est une adaptation de son code avec l'utilisation de Entreprise Library Caching Block ainsi que l'ajout de nouvelles méthodes FlushCache, UpdateCacheItem et DeleteCacheItem.
Voici le Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
namespace iCom.Core.Linq
{
public static class LinqCache
{
private static ICacheManager _cache;
static LinqCache()
{
_cache = CacheFactory.GetCacheManager("Default");
}
public static List<LinqObject> GetCacheItem<LinqContext, LinqObject>()
where LinqObject : class
where LinqContext : System.Data.Linq.DataContext, new()
{
//Build the cache item name. Tied to context and the object.
string cacheItemName = typeof(LinqObject).ToString() + "_" + typeof(LinqContext).ToString();
//Check to see if they are in the cache.
List<LinqObject> cacheItems = _cache[cacheItemName] as List<LinqObject>;
if (cacheItems == null)
{
//It's not in the cache -or- is the wrong type.
//Create a new list.
cacheItems = new List<LinqObject>();
//Create the contect in a using{} block to ensure cleanup.
using (LinqContext dc = new LinqContext())
{
try
{
//Get the table with the object from the data context.
System.Data.Linq.Table<LinqObject> table = dc.GetTable<LinqObject>();
//Add to the generic list. Detaches from the data context.
cacheItems.AddRange(table);
//Add to the cache. No absolute expirate and a 60 minute sliding expiration
_cache.Add(cacheItemName, cacheItems, CacheItemPriority.Normal,
null, new AbsoluteTime(TimeSpan.FromMinutes(60)));
}
catch (Exception ex)
{
//Something bad happened.
throw new ApplicationException("Could not retrieve the request cache object", ex);
}
}
}
//return ...
return cacheItems;
}
public static void FlushCache<LinqContext, LinqObject>()
where LinqObject : class
where LinqContext : System.Data.Linq.DataContext, new()
{
//Build the cache item name. Tied to context and the object.
string cacheItemName = typeof(LinqObject).ToString() + "_" + typeof(LinqContext).ToString();
//Check to see if they are in the cache.
List<LinqObject> cacheItems = _cache[cacheItemName] as List<LinqObject>;
if (cacheItems != null)
_cache.Remove(cacheItemName);
}
public static void UpdateCacheItem<LinqContext, LinqObject>(LinqObject obj)
where LinqObject : class, IEquatable<LinqObject>
where LinqContext : System.Data.Linq.DataContext, new()
{
//Build the cache item name. Tied to context and the object.
string cacheItemName = typeof(LinqObject).ToString() + "_" + typeof(LinqContext).ToString();
//Check to see if they are in the cache.
List<LinqObject> cacheItems = _cache[cacheItemName] as List<LinqObject>;
if (cacheItems != null)
{
Boolean founded = false;
for (int i = 0; i < cacheItems.Count; i++)
{
if (obj.Equals(cacheItems[i]))
{
cacheItems[i] = obj;
founded = true;
break;
}
}
if (!founded)
{
cacheItems.Add(obj);
_cache.Remove(cacheItemName);
_cache.Add(cacheItemName, cacheItems, CacheItemPriority.Normal,
null, new AbsoluteTime(TimeSpan.FromMinutes(60)));
}
else
{
_cache.Remove(cacheItemName);
_cache.Add(cacheItemName, cacheItems, CacheItemPriority.Normal,
null, new AbsoluteTime(TimeSpan.FromMinutes(60)));
}
}
else
{
GetCacheItem<LinqContext, LinqObject>();
}
}
public static void DeleteCacheItem<LinqContext, LinqObject>(LinqObject obj)
where LinqObject : class, IEquatable<LinqObject>
where LinqContext : System.Data.Linq.DataContext, new()
{
//Build the cache item name. Tied to context and the object.
string cacheItemName = typeof(LinqObject).ToString() + "_" + typeof(LinqContext).ToString();
//Check to see if they are in the cache.
List<LinqObject> cacheItems = _cache[cacheItemName] as List<LinqObject>;
if (cacheItems != null)
{
Boolean founded = false;
for (int i = 0; i < cacheItems.Count; i++)
{
if (obj.Equals(cacheItems[i]))
{
cacheItems.Remove(cacheItems[i]);
founded = true;
break;
}
}
if (founded)
{
_cache.Remove(cacheItemName);
_cache.Add(cacheItemName, cacheItems, CacheItemPriority.Normal,
null, new AbsoluteTime(TimeSpan.FromMinutes(60)));
}
}
}
}
}
J'ai personnellement dérivé toutes les classes de mon dbml LinqToSql par IEquatable<LinqObject> afin de pouvoir faire une comparaison de mes objets dans le cache et donc les mettre a jours ou les supprimer.
Configuration de Entreprise Library Caching Block dans le Web.config ou App.config
<configSections>
<section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<!-- ***************************************************************** -->
<!-- ** Entreprise Library Caching Configuration Section ** -->
<!-- ***************************************************************** -->
<cachingConfiguration defaultCacheManager="Configuration">
<cacheManagers>
<add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000" numberToRemoveWhenScavenging="10" backingStoreName="Null Storage" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Configuration" />
<add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000" numberToRemoveWhenScavenging="10" backingStoreName="Null Storage" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Default" />
</cacheManagers>
<backingStores>
<add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Null Storage" />
</backingStores>
</cachingConfiguration>
Avec cette classe il est donc très simple de s'en servir comme ceci :
Récupération d'un objet (ou collection) à partir du Cache
var q = from p in LinqCache.GetCacheItem<DbStoreDataContext, T_Customer>()
where p.Email == Email
select p;
T_Customer dataItem = q.SingleOrDefault<T_Customer>();
Mise a jours d'un objet dans le Cache
T_Customer dataItem = new T_Customer();
LinqCache.UpdateCacheItem<DbStoreDataContext, T_Customer>(dataItem);
Suppression d'un objet du Cache
LinqCache.DeleteCacheItem<DbStoreDataContext, T_CartDetail>(originalCartDetail);
Et voila rien de plus simple :)
Views(2473)

