Traduction▲
Cet article est la traduction la plus fidèle possible de l'article original : Creating Model Classes with LINQ to SQL (C#)
Introduction▲
Le but de ce tutoriel est de présenter une méthode de création de modèle de classes pour une application ASP.NET MVC. Dans ce tutoriel, vous apprenez comment construire des modèles de classes et réaliser des accès aux bases de données en tirant profit de Microsoft LINQ to SQL.
Dans ce tutoriel, nous construisons une application basique des gestions de films. Nous commençons par créer l'application de gestion de films de la manière la plus rapide et la plus facile possible. Nous réalisons tous nos accès de données directement à partir de nos actions de contrôleur.
Ensuite, vous apprenez comment utiliser le pattern Repository. Utiliser le pattern Repository requiert un peu plus de travail. Cependant, l'avantage d'adopter ce pattern est de vous permettre de construire des applications qui s'adaptent facilement aux changements et qui peuvent être facilement testées.
Qu'est-ce qu'un modèle de classe ?▲
Un modèle MVC contient l'entièreté de la logique de l'application qui n'est pas incluse dans une vue MVC ou un contrôleur MVC. En particulier, un modèle MVC contient l'entièreté de votre application métier et la logique d'accès aux données.
Vous pouvez utiliser une variété de différentes technologies pour implementer votre logique d'accès aux données. Par exemple, vous pouvez construire vos classes d'accès aux données en utilisant le Microsoft Entity Framework, NHibernate, Subsonic ou les classes ADO.NET.
Dans ce tutorial, j'utilise LINQ to SQL pour requêter et mettre à jour la base de données. LINQ to SQL vous fournit une méthode très facile d'intéraction avec une base de données Microsoft SQL Server. Cependant, il est important de comprendre que le framework ASP.NET MVC n'est lié d'aucune façon à LINQ to SQL. ASP.NET MVC est compatible avec n'importe quelle technologie d'accès aux données.
Création d'une base de données Movie▲
Dans ce tutorial - dans le but d'illustrer comment vous pouvez construire des modèles de classes - nous construisons une simple application de gestion de films. La première étape est de créer une nouvelle base de données. Cliquez-droit sur le répertoire App_Data dans la fenêtre de votre explorateur de solution and sélectionnez l'option Add, New Item. Sélectionnez le template SQL Server Database, donnez-lui le nom MoviesDB.mdf et cliquez sur le bouton Add (voir Figure 1).
Après avoir créé la nouvelle base de données, vous pouvez l'ouvrir en double cliquant sur le fichier MoviesDB.mdf du répertoire App_Data. Double cliquer sur le fichier MoviesDB.mdf ouvre la fenêtre Server Explorer (voir Figure 2).
La fenêtre Server Explorer est appelée la fenêtre Database Explorer quand vous utilisez Visual Web Developer.
Nous avons besoin d'ajouter une table à notre base de données qui représentera nos films. Cliquez-droit sur le répertoire Tables et sélectionnez l'option Add New Table. En sélectionnant cette option, le designer de table s'ouvre (voir Figure 3).
Nous avons besoin d'ajouter les colonnes suivantes à la table de notre base de données :
Nom colonne | Type de données | Null autorisé ? |
---|---|---|
Id | Int | Faux |
Title | nvarchar(200) | Faux |
Director | nvarchar(50) | Faux |
Vous avez besoin d'effectuer deux choses spéciales sur la colonne Id. Tout d'abord, vous avez besoin de marquer la colonne Id comme colonne clé primaire en sélectionnant la colonne en question dans le designer de table et en cliquant sur l'icône de la clé. LINQ to SQL requiert que vous spécifiiez votre colonne clé primaire quand vous réalisez des insertions et mises à jour de la base de données.
Ensuite, vous avez besoin de marquer la colonne Id comme une colonne Identity en assignant la valeur Yes à la propriété Is Identity (voir Figure 3). Une colonne Identity est une colonne qui permet d'assigner automatiquement un nouveau nombre quand vous ajoutez une nouvelle ligne de données à une table.
Création des classes LINQ to SQL▲
Notre modèle MVC contiendra des classes LINQ to SQL qui représentent la table tblMovie de la base de données. La façon la plus facile pour créer ces classes LINQ to SQL est de cliquez droit sur le répertoire Models, sélectionnez Add, New Item, sélectionnez le template LINQ to SQL Classes, donnez comme nom Movie.dbml et cliquez sur le bouton Add (voir Figure 4).
Immédiatement après avoir créé le fichier Movie LINQ to SQL Classes, l'Object Relational Designer apparait. Vous pouvez glisser les tables de la base de données à partir de la fenêtre Server Explorer sur l'Object Relational Designer pour créer des classes LINQ to SQL qui représentent les tables de bases de données en question. Nous avons d'ajouter la table tblMovie de la base de données sur l'Object Relational Designer (voir Figure 5).
Par défaut, l'Object Relational Designer crée une classe avec le même nom que celui de la table de la base de données que vous avez glissez dans le designer. Cependant, nous ne voulons pas appeler notre classe tblMovie. Par conséquent, cliquez sur le nom de la classe dans le designer et changez le nom de la classe en Movie.
Finalement, pensez à cliquez sur le bouton Save (Il a un icône de disquette) pour sauvegarder le fichier LINQ to SQL Classes. Dans le cas contraire, l'Object Relational Designer ne générera pas les changements dans les classes LINQ to SQL.
Utilisation de LINQ to SQL dans un Contrôleur Action▲
Maintenant que nous avons nos classes LINQ to SQL, nous pouvons utiliser ces classes pour récupérer des données de la base de données. Dans cette section, nous apprenons comment utiliser les classes LINQ to SQL directement dans un contrôleur action. Nous afficherons la liste des films de la table tblMovies de la base de données dans une vue MVC.
Tout d'abord, nous avons besoin de modifier la classe HomeController. Cette classe peut être trouvée dans le répertoire Controllers de votre application. Modifiez la classe pour qu'elle ressemble à la classe du Listing 1.
using
System.
Linq;
using
System.
Web.
Mvc;
using
MvcApplication1.
Models;
namespace
MvcApplication1.
Controllers
{
[HandleError]
public
class
HomeController :
Controller
{
public
ActionResult Index
(
)
{
var
dataContext =
new
MovieDataContext
(
);
var
movies =
from
m in
dataContext.
Movies
select
m;
return
View
(
movies);
}
}
}
L'action Index() dans le Listing 1 utilise une classe DataContext LINQ to SQL (le MovieDataContext) ppur représenter la base de données MoviesDB. La classe MovieDataContext a été générée par l'Object Relational Designer de Visual Studio.
Une requête LINQ est exécute sur le DataContext pour récupérer l'ensemble des films de la table tblMovies de la base de données. La liste de films est assignée à une variable locale nommée movies. Finalement, la liste des films est passée à la vie au travers de la " view data ".
Afin d'afficher les films, nous avons ensuite besoin de modifier la vue Index. Vous pouvez trouver la vue Index dans le répertoire Views\Home\. Mettez à jour la vue Index pour qu'elle ressemble à la vue dans le listing 2.
<%
@ Page Language=
"C#"
MasterPageFile=
"~/Views/Shared/Site.Master"
AutoEventWireup=
"true"
CodeBehind=
"Index.aspx.cs"
Inherits=
"MvcApplication1.Views.Home.Index"
%>
<%
@ Import Namespace=
"MvcApplication1.Models"
%>
<
asp:
Content ID=
"indexContent"
ContentPlaceHolderID=
"MainContent"
runat=
"server"
>
<
ul>
<%
foreach
(
Movie m in
(
IEnumerable)ViewData.
Model)
{
%>
<
li>
<%=
m.
Title %>
</
li>
<%
}
%>
</
ul>
</
asp:
Content>
A noter que la vue Index modifiée inclut une directive <%@ import namespace %> au début de la vue. Cette directive importe l'espace de nom MvcApplication1.Models. Nous avons besoin de cet espace de nom afin de pouvoir travailler avec les classes du modèle - en particulier, la classe Movie - dans la vue.
La vue du Listing 2 contient une boucle foreach qui itère chaque élément contenu par la propriété ViewData.Model.
A noter que la valeur de la propriété ViewData.Model est convertie en IEnumerable. Ceci est nécessaire afin d'itérer le contenu de ViewData.Model. Une autre option ici est de créer une vue fortement typée. Qaund vous créez une vue fortement typée, vous convertissez la prorpriété ViewData.Model en un type précis dans le code-behind de la classe de la vue.
Si vous lancez l'application après modification de la classe HomeController et de la vue Index, vous obtiendrez alors une page blanche. Vous obtiendrez une page blanche étant donné qu'il n'y a aucun enregistrement de film dans la table tblMovies de la base de données.
Afin d'ajouter des enregistrements dans la table tblMovies de la base de données, cliquez droit sur la table tblMovies dans la fenêtre Server Explorer (fenêtre Database Explorer dans Visual Web Developer) et sélectionnez l'option Show Table Data. Vous pouvez insérer des enregistrements de films en utilisant la grille qui apparait (voir Figure 6).
Après avoir créé quelques enregistrements dans la table tblMovies de la base de données et lance l'application, vous verrez la page en Figure 7. Tous les films de la base de données sont affichés dans une liste.
Utilisation du Pattern Repository▲
Dans la section précédente, nous avons utilisez les classes LINQ to SQL directement dans un contrôleur action. Nous avons utilisé la classe MovieDataContext directement à partir de l'action Index() du contrôleur. Il n'y a rien de mal en effectuant ceci dans le cas d'application simple. Cependant, travailler directement avec LINQ to SQL dans une classe contrôleur crée des prolbèmes quand vous avez besoin de construire une application beaucoup plus complexe.
Utiliser LINQ to SQL dans une classe contrôleur rend les choses difficiles lorsque vous voudrez changer de technologie d'accès aux données dans le future. Par exemple, vous pouvez décider de passer l'utilisation de Microsoft LINQ to SQL à l'utilisation de Microsoft Entity Framework comme technologie pour votre accès aux données. Dans ce cas, vous aurez besoin de récrire chaque contrôleur qui accède à la base de données au sein de votre application.
Utiliser LINQ to SQL dans une classe contrôleur rend aussi difficile la construction de tests unitaires pour votre application. Normalement, vous ne voulez pas interagir avec une base de données lors de l'exécution de vos testes unitaires. Vous voulez utiliser vos tests unitaires pour tester la logique de l'application et non votre serveur de base de données.
Afin de construire une application MVC qui supporte mieux les changements futurs and qui peut être facilement testable, vous devrez considérer le pattern Repository. Lorsque vous utilisez le pattern Repository, vous créez une classe repository séparée qui contient tout votre logique à la base de données.
Lorsque vous créez la classe repository, vous créer une interface qui contient toutes les méthodes utilisées par la classe repository. A l'intérieur de vos contrôleurs, vous écrivez le code par rapport à l'interface à la place de celui du repository. De cette façon, vous pouvez implémenter le repository en utilisant différentes technologies d'accès aux données dans le futur.
L'interface du Listing 3 est nommée IMovieRepository et elle contient une méthode unique nommée ListAll().
using
System.
Collections.
Generic;
namespace
MvcApplication1.
Models
{
public
interface
IMovieRepository
{
IList<
Movie>
ListAll
(
);
}
}
La classe repository du Listing 4 implémente l'interface IMovieRepository. Notez qu'elle contient une méthode nommée ListAll() qui correspond à la méthode requise par l'interface IMovieRepository.
using
System.
Collections.
Generic;
using
System.
Linq;
namespace
MvcApplication1.
Models
{
public
class
MovieRepository :
IMovieRepository
{
private
MovieDataContext _dataContext;
public
MovieRepository
(
)
{
_dataContext =
new
MovieDataContext
(
);
}
#region IMovieRepository Members
public
IList<
Movie>
ListAll
(
)
{
var
movies =
from
m in
_dataContext.
Movies
select
m;
return
movies.
ToList
(
);
}
#endregion
}
}
Au final, la classe MoviesController du Listing 5 utilise le pattern Repository. Elle n'utilise plus les classes LINQ to SQL directement.
using
System.
Web.
Mvc;
using
MvcApplication1.
Models;
namespace
MvcApplication1.
Controllers
{
public
class
MoviesController :
Controller
{
private
IMovieRepository _repository;
public
MoviesController
(
) :
this
(
new
MovieRepository
(
))
{
}
public
MoviesController
(
IMovieRepository repository)
{
_repository =
repository;
}
public
ActionResult Index
(
)
{
return
View
(
_repository.
ListAll
(
));
}
}
}
Notez que la classe MoviesController du Listing 5 a deux constructeurs. Le premier constructeur, le constructeur sans paramètre, est appelé quand votre application est en train de tourner. Ce constructeur crée une instance de la classe MovieRepository et la passe au second constructeur.
Le second constructeur a un paramètre unique : un paramètre IMovieRepository. Ce constructeur assigne simplement la valeur du paramètre au champ de la classe nommé _repository.
La classe MoviesController tire profit du pattern softwaee design appelé le pattern Dependency Injection. Plus précisément, il utilise quelque chose appelé Constructor Dependency Injection. Vous pouvez en savoir sur ce pattern en lisant l'article suivant écrit par Martin Fowler :
http://martinfowler.com/articles/injection.html
A noter que tous le code de la classe MoviesController (à l'exception du premier constructeur) interagit avec l'interface IMovieRepository à la place de la classe MovieRepository. Le code interagit avec une interface abstraite à la place d'une implémentation concrète de l'interface.
Si vous voulez modifier la technologie d'accès aux données utilisée par l'application, vous pouvez alors simplement implementer l'interface IMovieRepository avec une classe qui utilise une technologie alternative d'accès à la base de données. Par exemple, vous pourriez créer une classe EntityFrameworkMovieRepository ou une classe SubSonicMovieRepository. Etant donné que la classe contrôleur est programmée par rapport à l'interface, vous pouvez donner une nouvelle implémentation de IMovieRepository à la classe contrôleur et la classe continuera à fonctionner.
De plus, si vous voulez tester la classe MoviesController, vous pouvez passer au HomeController une classe repository avec de faux films. Vous pouvez implémenter la classe IMovieRepository avec une classe qui n'accède pas encore à la base de données mais qui contient toutes les méthodes requises de l'interface IMovieRepository. De cette façon, vous pouvez faire des testes unitaires sur la classe MoviesController sans actuellement accéder à une vrai base de données.
Conclusion▲
Le but de ce tutorial était de présenter comment vous pouvez créer des classes de modèle MVC en tirant profit des avantages de Microsoft LINQ to SQL. Nous avons analysé deux stratégies pour afficher des données provenant d'une base de données dans une application MVC. Tout d'abord, nous avons créé des classes LINQ to SQL et nous avons utilisé les classes directement dans un contrôleur action. L'utiliser des classes LINQ to SQL dans un contrôleur vous permet de rapidement et facilement afficher des données de base de données dans une application MVC.
Ensuite, nous avons exploré une légèrement plus difficile, mais définitivement plus vertueux, façon pour afficher des données d'une base de données. Nous avons tiré profit des avantages du pattern Repository et placé toute notre logique d'accès aux données dans une classe repository séparée. Dans notre contrôleur, nous avons écrit tous le code sur base d'une interface et non d'une classe concrète. L'avantage du pattern Repository est que cela nous permet de changer facilement dans le futur de technologie d'accès à une base de données et aussi d'effectuer facilement des testes unitaires sur nos classes contrôleurs.