logo

log de Julien Corioland (MVP)

Quand les technologies .NET deviennent passion...

all posts in the category : Entity Framework


[EN][Entity Framework] Database first approach with EF 4.1

by Julien Corioland the 9/22/2011

As you probably already know the last version of Entity Framework (4.1) supports a new development scenario called “Code first” (also called code only in some cases). It consists to develop the .NET entities (POCOs) before the SQL relational model, create the database, map these entities to table and columns at runtime according the class definitions. To do that, there is no need of an EDMX file, metadata and mapping are based on conventions and attributes.

Entity Framework 4.1 provides a lot of new functionalities that may be used even if the “code first” approach is not applied for many reasons (existing database, database created and maintained by a DBA that doesn’t know .NET or Entity Framework…). To be able to use the new features of Entity Framework 4.1 it’s possible to continue with the database first approach and use an EDMX file to do the mapping between .NET objects (POCOs) and SQL tables and columns. This post explains how to do that !

Import the Entity Framework 4.1 library

To use EF 4.1 it’s recommended to reference the related NuGet package using the NuGet management console in Visual Studio. Right click on the project that should reference the library and choose Manage NuGet packages…

In the NuGet management console, search for “Entity Framework” and click Install to download and reference the EntityFramework.dll library.

Download the T4 code generation templates for EF 4.1

To generate the DbContext and the .NET entities from the EDMX definition it’s possible to download two code generation templates from the Visual Studio Extensions manager. Open it and search for “DbContext” in the online gallery :

Install the “ADO.NET C# DbContext Generator” item (or VB.NET).

Delete the code generation tool from EDMX properties

When an ADO.NET entity data model is added to a project, it uses the default code generation template. To avoid this, you have to remove this tool in the property window of the EDMX file :

Be careful if you’re working on an existing project where generated code may be in use !

Add the templates to the project

Now you’ve to add the two generation code templates to the project. To do that add a new item of type “ADO.NET C# DbContext Generator” from the add item menu :

In these two files, find the text $edmxInputFile and replace it by the relative path to the EDMX file.

Save the files. Automatically the DbContext and the entities are generated :

Now you are ready to use the DbContext and query the database through LINQ to Entites !

using (var dbContext = new BlogContainer()) {
    var posts = dbContext.Posts.Where(p => p.IsPublished).ToList();

    return View(posts);
}

After each change on the edmx file just run the custom tool on the two T4 templates to regenerate the DbContext and the entities.

Hope this helps Winking smile


read full post -

[Entity Framework] Continuer à utiliser un EDMX avec EF 4.1

by Julien Corioland the 9/19/2011

Le titre de ce post vous a peut-être suppris puisque l’une des nouveautés la plus plébicitée de Entity Framework 4.1 est la possibilité de s’affranchir d’un modèle EDMX et d’adopter une stratégie Code First : les entités .NET permettent de générer le modèle de données SQL.

Pourtant, Entity Framework 4.1 apporte de nombreuses autres nouveautés, notamment en terme de gestion de l’état des entités, la mise à jour d’entités dans un contexte state-less (notamment), de requêtage… via des méthodes beaucoup plus simples que précédement.

Ce post à pour but d’expliquer comment utiliser Entity Framework 4.1 tout en continuant d’utiliser un EDMX et une stratégie Database First !

Importer la librairie Entity Framework 4.1

Pour pouvoir utiliser EF 4.1, le plus simple est de référencer le package NuGet associé. Faites un clic droit sur votre projet Visual Studio puis cliqué sur “Manage NuGet packages…” :

EF41_01

Dans la fenêtre qui s’affiche, recherchez Entity Framework :

EF41_02

Cliquez sur “Install”, acceptez les conditions. La librairie EntityFramework.dll va être téléchargée et référencée dans le projet.

Télécharger les templates de génération de code (T4) pour EF 4.1

Afin de générer le code propre à EF 4.1 (entités et DbContext) il est possible de télécharger un template d’item via le gestionnaire d’extension de Visual Studio. Placez-vous dans la galerie en ligne et recherchez DbContext :

EF41_03

Installez l’élément “ADO.NET C# DbContext Generator” (ou VB si vous le souhaitez Smile).

Supprimer l’outil de génération de code de votre EDMX

Afin que le code ne soit plus généré par l’EDMX, éditez les propriétés de ce dernier et supprimer l’outil personnalisé :

EF41_04

Attention : ne faites pas celà dans un projet qui utilise les éléments de code généré par l’EDMX Entity Framework “classique”.

Ajouter les templates au projet

Maintenant, ajoutez un nouvel item de type “ADO.NET C# DbContext Generator” au projet.

EF41_05

Identifiez la ligne de code suivante dans chacun des templates et modifiez la chaine $edmxInputFile$ par le chemin relatif vers votre fichier EDMX.

EF41_06

Dès lors, lorsque vous enregistrez les templates, du code devrait être généré : les entités et le DbContext.

EF41_07

Et voilà, vous pouvez utilisez le contexte généré pour attaquer votre base de données !

using (var dbContext = new BlogContainer()) {
    var posts = dbContext.Posts.Where(p => p.IsPublished).ToList();

    return View(posts);
}

Après modification de l’EDMX, il suffit de regénérer les templates T4 pour les mettre à jour et de recompiler le tout Smile

A bientôt Winking smile


read full post -

[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 -

  • prev
  • next