EntityFramework.Patterns : Repository & Unit Of Work

Publié par Fabrice Michellonet sous le(s) label(s) , le 13 juillet 2011

Je vous propose un très rapide post pour faciliter la prise en main des Patterns Repository et Unit Of Work disponibles dans EntityFramework.Patterns

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<Product> Products { get; set; }
    public virtual DbSet<ProductCategory> Categories { get; set; }

    public Context()
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
    }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ProductCategoryId { get; set; }
    public virtual ProductCategory ProductCategory { get; set; }
}

public class ProductCategory
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Commençons par créer le Repository

using(Context ctx = new Context())
{
    DbContextAdapter adapter = new DbContextAdapter(ctx);
    IRepository<Product> productRepo = new Repository<Product>(adp);
    ...
}

Interrogeons la base pour ramener l'ensemble des produits :

IEnumerable<Product> lst = productRepo.GetAll();

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<Product> lst = productRepo.Find(
                p => p.Id < 100 && p.Name.Contains("o") && p.Name.Length < 20);

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.

Release d'EntityFramework.Patterns

Publié par Fabrice Michellonet sous le(s) label(s) le 7 juillet 2011

Bon ça y est je me suis décidé à trouver un toit pour EntityFramework.Patterns, une librairie qui s'adossant à Entity Framework 4.1, propose l'implémentation de patterns couramment nécessaire lorsqu'on utilise un ORM.

Je n'ai toujours pas cédé aux appels des sirènes de Github; EntityFramework.Patterns est donc hébergé sur Codeplex. Vous trouverez également la librairie sur nuget... d'ailleurs elle y était présente bien avant la création du repository sur codeplex.

Pour l'installer via nuget, rien de plus simple :

install-package EntityFramework.Patterns

A l'heure actuelle, vous trouverez deux patterns d'infrastructure :

  • Repository
  • Unit Of work
Rob Conery les définissaient ainsi récemment :
The Repository Pattern is all about encapsulating calls to your DB as methods to do a thing. These calls are (typically) atomic.

Tout est dit! L'avantage est simple, couplé avec un/des décorateurs il sera facile d'ajouter des comportements transverses (cache, securité, log etc...)
UnitOfWork is - well it’s a way of transactionally flushing changes to a persistence store (aka Database)

Ce qui permet de découpler facilement la gestion d'état des entités et le requêtage.

Des patterns d'infrastructure pour l'instant, qui seront rapidement suivit par les patterns suivants :

  • Repository Decorator
  • Audit log
  • Audit trail
  • Archived entity
  • Internationalized entity

Dans un tout prochain post je présenterais ces deux patterns Repostitory<T> et UnitOfWork.

FEZ Domino

Publié par Fabrice Michellonet sous le(s) label(s) , le 16:51

Un rapide post pour vous faire partager ma joie de ce jour.

J'ai enfin reçu la commande que j'avais passé sur Roboshop il y a bientôt un mois (ils déconnent un peu chez Roboshop sur les délai...) Bref, entre autre dans le colis :

  1. Micro-contrôleur Fez Domino
    • Processeur 72Mhz 32-bit ARM7 LPC2388
    • ~148KB free Flash
    • ~62KB free RAM

    fez domino

  2. Un servo controlleur SSC-32
    • Peut gérer jusqu'à 32 servo moteurs.

    SSC-32

C'est vraiment petit ces trucs la, pour vous donner une idée, les voici à côté d'une pile 9V.

Domino & SSC-32

Mon premier défit va être de tenter le portage d'un conteneur DI sur cette plateforme. Je sens que ça va être chaud!

Ensuite, je crois que je vais tenter la construction d'un Hexapode... d’où l'achat du SSC-32.