logo

log de Julien Corioland (MVP)

Quand les technologies .NET deviennent passion...

archives : July 2011


[ASP.NET MVC] Repository Entity Framework dans un contexte stateless

by Julien Corioland the 7/27/2011

Les mappeurs objets relationnels comme Entity Framework apportent de nombreux avantages lors du développement d’application utilisant des bases de données comme système de stockage. Au delà d’effectuer un mapping entre le monde objet et le monde relationnel, permettre la génération de requête SQL à partir du langage .NET LINQ, Entity Framework fournit également un système de détection de changement sur les entités afin de générer uniquement le nécessaire lorsque l’on demande un commit sur la base de données.

L’idée est assez simple au final : toute entité chargée depuis un contexte Entity Framework possède un état :

  • Unchanged : l’entité n’est pas modifiée, aucune requête SQL ne sera générée pour celle-ci lors du commit
  • Added : l’entité a été ajoutée au contexte, un ordre INSERT sera généré lors du commit
  • Modified : l’entité a été modifiée depuis qu’elle a été chargée via le contexte, un ordre UPDATE sera généré lors du commit
  • Deleted : l’entité a été supprimée du contexte, un ordre DELETE sera généré lors du commit

Il existe un dernier état que peut prendre une entité : Detached, c’est à dire qu’elle n’a pas été récupérée via le contexte Entity Framework.

L’état d’une entité est maintenue au sein du contexte par l’ObjectStateManager. Dès lors que le contexte Entity Framework est disposé, toutes les informations relatives au suivi des changements sont perdues.

ASP.NET MVC de part sa nature stateless force une très courte durée de vie pour un contexte Entity Framework : j’envoie une requête HTTP au serveur, le contexte Entity Framework est créé, la récupération de données est effectuée, le contexte est libéré et la connection à la base de données fermée, impliquant que le suivi des changements soit impossible dans ce cas : comment replacer mon objet dans le contexte lors que je post un formulaire HTML ?

Pour l’exemple, nous allons travailler avec l’entity data model suivant :

image_thumb1

Créeons à présent la classe repository qui va permettre d’effectuer les opérations de CRUD sur un item de type Blog :

public class BlogRepository : IDisposable
{
    private readonly BlogsContainer _blogsContainer = new BlogsContainer();

    public void AddBlog(Blog blog)
    {
        _blogsContainer.Blogs.AddObject(blog);
        _blogsContainer.SaveChanges();
    }

    public Blog GetBlog(int blogId)
    {
        return _blogsContainer.Blogs.SingleOrDefault(b => b.Id == blogId);
    }

    public IEnumerable<Blog> GetBlogs()
    {
        return _blogsContainer.Blogs.ToList();
    }

    public void DeleteBlog(Blog blog)
    {
        
    }

    public void UpdateBlog(Blog blog)
    {
        
    }

    public void Dispose()
    {
        _blogsContainer.Dispose();
    }
}

Comme il est possible de le constater dans l’extrait de code ci-dessus, les opérations Add/Get sont réalisées de manière tout à fait classique sur l’object context Entity Framework. Cela va en revanche différer pour les méthodes Delete et Update, volontairement laissées vides pour le moment.

En effet, dans un contexte stateless, il n’est pas possible de bénéficier directement du mécanisme de change tracking proposé par Entity Framework : il faut auparavant attacher l’objet au contexte s'il ne l’est pas déjà.

Pour cela, l’object context expose une propriété ObjectStateManager qui va permettre de récupérer une ObjectStateEntry associée a une entité : si celle-ci existe, l’élément est connu du contexte, sinon il est inconnu :

ObjectStateEntry stateEntry;
if (_blogsContainer.ObjectStateManager.TryGetObjectStateEntry(blog, out stateEntry))
{
    //l'objet Blog est connu du change tracker
}
else
{
    //l'objet blog est inconnu du change tracker
}

Du coup, dans le cas d’un delete, on vérifie si l’objet est connu du change tracker : si oui, pas de souci, sinon on attache l’objet au contexte avant de demander sa suppression :

public void DeleteBlog(Blog blog)
{
    ObjectStateEntry stateEntry;
    if (!_blogsContainer.ObjectStateManager.TryGetObjectStateEntry(blog, out stateEntry))
    {
        _blogsContainer.Blogs.Attach(blog);
    }
    
    _blogsContainer.Blogs.DeleteObject(blog);
    _blogsContainer.SaveChanges();
}

De la même manière, pour la mise à jour il faut vérifier si l’objet est connu du change tracker. Si oui, on va pouvoir utiliser la méthode “ApplyCurrentValues” de l’object set Blogs pour appliquer les changements et forcer le passage de l’entité dans l’état “Modified”. Sinon, il faut forcer le changement d’état via l’object state manager, après avoir attacher l’entité blog :

public void UpdateBlog(Blog blog)
{
    ObjectStateEntry stateEntry;
    if (!_blogsContainer.ObjectStateManager.TryGetObjectStateEntry(blog, out stateEntry))
    {
        _blogsContainer.Blogs.Attach(blog);
        _blogsContainer.ObjectStateManager.ChangeObjectState(blog, System.Data.EntityState.Modified);
    }
    else
    {
        _blogsContainer.Blogs.ApplyCurrentValues(blog);
    }

    _blogsContainer.SaveChanges();
}

Et voilà un repository ultra simple, fonctionnel et adapté au développement d’applications stateless avec ASP.NET MVC.

A bientôt Winking smile


read full post -

Nouveau blog : aspnet mvc 3, windows azure, entity framework…

by Julien Corioland the 7/27/2011

J’ai décidé d’externaliser mon blog et de quitter la plateforme Dotnet-France, sur laquelle mon ancien blog est toujours hébergé.

Pourquoi ce choix ? Tout simplement parce que je voulais écrire moi-même mon blog afin qu’il corresponde exactement à mes besoins et au passage cela m’a permis de prendre en main un certain nombre de technologies auxquelles je voulais me consacrer depuis un petit moment : ASP.NET MVC 3 et Windows Azure.

Vous l’aurez compris, ce blog a donc été développé avec ASP.NET MVC 3, et utilise le View Engine Razor (qui envoie franchement du paté!) et est hébergé sur Windows Azure pour la partie compute et Windows Azure Storage (Table) pour la partie Data.

Afin de mettre en place certains conceptes (injection de dépendances, scénario d’hébergement in cloud / on premises…), j’ai également développé un provider Entity Framework code first me permettant d’attaquer une base de données Sql Azure à la place du table storage.

J’ai identifié certains point assez intéressants lors du développement de ce blog, aussi je vais tâcher de publier des posts sur le développement d’applications web ASP.NET MVC 3 hébergées dans Windows Azure ou utilisant Entity Framework, l’injection de dépendance...

Mon ancien blog restera en ligne, mais ne sera plus alimenté, donc pensez à mettre à jour vos flux RSS si vous voulez continuer à suivre mes posts Winking smile

Comme avant, je n’ai pas véritablement de sujet de prédilection (bon ok, Silverlight / Windows Phone, si je dois choisir) mais j’aime toucher à tout, donc je continuerai à parler des technologies .NET en général sur ce blog, au fur et à mesure de mes découvertes / projets Smile

N’hésitez pas à me faire part de vos commentaires / remarques / suggestions quant à ce nouveau blog !

A bientôt pour de nouvelles aventures…

Julien


read full post -

  • prev
  • next