EntityFramework.Patterns : Repository & Unit Of Work
Je vous propose un très rapide post pour faciliter la prise en main des Patterns Repository
Pour simplifier le sujet, le but du pattern Repository est de donner au développeur une passerelle de requêtage unifiée, via des opérations (le plus souvent) atomiques.
Unit Of Work, est la quant à lui pour valider transactionnellement un ensemble de modifications faites sur les données.
Pour la version longue vous pourrez trouver votre bonheur sur le site de Martin Fowler ici pour le Repository et ici pour Unit Of Work
Partons d'un modèle simplissime comme celui ci-dessous :
public class Context : DbContext { public virtual DbSet
Commençons par créer le Repository
using(Context ctx = new Context()) { DbContextAdapter adapter = new DbContextAdapter(ctx); IRepository
Interrogeons la base pour ramener l'ensemble des produits :
IEnumerable
Ramenons le premier élément dont le nom commence par "Bike"
Product prod = productRepo.First(p => p.Name.StartsWith("Bike"));
L'utilisation de la méthode Single a pour effet de ramener un seul élément de la base de données; mais lève une exception si plusieurs éléments répondent aux critères demandés.
productRepo.Single(p => p.Name.StartsWith("Roc"))
Find(), permet de filtrer en fonction de plusieurs critères :
IEnumerable
Toutes ces méthodes acceptent optionnellement un ensemble de liens de navigation inter entités
params Expression<Func<T, object>>[] includeProperties
définissant les jointures à effectuer lors du requêtage.
Ainsi :
productRepo.First(p => p.ProductCategoryId != null , p => p.ProductCategory);
charge le produit et sa catégorie associée en une seule requete SQL; Cette façon de faire nous protège du fameux problème du Select N+1 lié au lazy loading utilisé par défaut avec Entity Framework.
Après l’interrogation de la base passons a la persistance de nos données. Pour cela nous allons faire appel au pattern UnitOfWork.
L'insertion d'un nouvel élément prend cette forme :
using(...) { ... IUnitOfWork unitOfWork = new UnitOfWork(adp); Product p = new Product{Name = "Skateboard"}; productRepo.Insert(p); unitOfWork.Commit(); }
Vous l'aurez compris la mise à jour et la suppression sont aussi simple que ca :
Product p = productRepo.First(c => c.Name == "Bike"); p.Name = "New bike"; productRepo.Update(p); Product delete = productRepo.First(p => p.Name.StartsWith("To be")); productRepo.Delete(delete); unitOfWork.Commit();
Dans les prochains jours je vous montrerais comment injecter Repository et Unit of work dans une couche Service par exemple avec un conteneur DI comme NInject.