25 novembre 2008

Lecture des données

Entity Framework offre 3 types de possibilité pour requêter la source de données :

  • LinQ To Entities

  • Entity SQL

  • Les méthodes génératrices de requête de "ObjectQuery<T>"
LinQ To Entities permet d'écrire des requêtes syntaxiquement proche du SQL, et cela directement en C# ou VB.Net. L'avantage majeur vient du fait que les requêtes produites sont vérifiées à la compilation et non plus à l'exécution. Comme pour chaque implémentation de LinQ, chaque requête est transformée en un arbre d'expression (créé par l'objet ObjectContext) qui est traduit en SQL par le fournisseur de données final. Le résultat d'une requête LinQ to Entities est de type "IQueryable<T>" où T est le type spécifié dans la clause SELECT de la requête.
Voici donc un exemple de requête LinQ to Entities :

var requete = from publication in bdd.Publication
select publication;

Le résultat est de type "IQueryable<Publication>". Il est possible d'itérer sur les résultats avec une simple boucle "foreach". Vu que "IQueryable<T>" implémente un énumérateur, sachez que la requête vers la source de données est uniquement exécutée lors du parcours des résultats. Pour plus d'information, veuillez vous référencer à la documentation officielle de l'objet "IQueryable<Publication>".
Linq to Entities supporte un ensemble de méthodes pour requêter la source de données dont voici une liste non exhaustive (url de la liste complète) :

  • Select, SelectMany

  • Where

  • GroupJoin, Join

  • All, Any

  • Distinct

  • Except

  • Intersect

  • Union

  • OrderBy, OrderByDescending, ThenBy, ThenByDescending

  • GroupBy

  • Average

  • Count, LongCount

  • Max, Min, Sum

  • OfType, Cast

  • First, FirstOrDefault

  • Skip, Take


Voici l'exemple d'une requête sélectionnant seulement les publications qui contiennent le mot "C#" dans leur titre :

var requete = from publication in bdd.Publication
where publication.Titre.Contains("C#")
select publication;

Pour plus d'informations sur les requêtes LinQ, je vous invite à lire l'article de Thomas Lebrun.
Il est aussi possible de requêter la source de données grâce à Entity SQL. C'est un langage héritant du vocabulaire et de la grammaire de type SQL. Ce langage permet de récupérer des produits scalaires, des ensembles de résultat et des graphes d'objet. Pour une description du langage, veuillez vous référer à la documentation officielle.
Voici l'exemple d'une requête récupérant toutes les publications stockées en base :


string chaineRequete = "SELECT VALUE p FROM Publication AS p";

// Définition de la requête de type ObjectQuery<Publication>
ObjectQuery<Publication> requete = new ObjectQuery<Publication>(chaineRequete, bdd, MergeOption.NoTracking);

En dernier choix, vous pouvez utiliser les méthodes du générateur de requêtes de la classe "ObjectQuery<T>". En voici un exemple :

// Définition de la requête de type ObjectQuery<Publication>
var requete = bdd.Publication.SelectValue<Publication>("it");

La suite de l'article fera uniquement référence à LinQ to Entities, mais toutes les requêtes faites sur le modèle peuvent être réalisées avec Entity SQL ou grâce aux méthodes du générateur de requêtes de la classe "ObjectQuery<T>".
Chaque entité en relation avec une autre possède une collection d'entités connexes. Cependant, celle-ci n'est pas initialisée par défaut. Pour naviguer vers ces entités, il est nécessaire de les charger explicitement :

  • soit en utilisant la méthode "Include" de "ObjectQuery<T>",

  • soit en utilisant la méthode "Load" appartenant à la classe "EntityReference<T>" ou à "EntityCollection<T>".


L'exemple suivant utilise la méthode "Include" pour récupérer explicitement, lors de la requête, l'éditeur et les auteurs associés aux publications :

using (Modele bdd = new Modele())
{
var requete = from publication in bdd.Publication.Include("Auteur").Include("Editeur") select publication;

requete.ToList().ForEach((Publication p) =>
{
Console.WriteLine("Publication : ID = {0} Titre = {1}", p.Id, p.Titre);

Console.WriteLine(" Editeur : ID = {0} Nom = {1}", p.Editeur.Id, p.Editeur.Nom);

p.Auteur.ToList().ForEach(a => Console.WriteLine(" Auteur : ID = {0} Nom = {1} {2}",a.Id,a.Prenom,a.Nom));
});
}

Voici un autre exemple avec l'utilisation de la méthode "Load". Remarquez que chaque collection ou chaque référence liée à une entité possède une propriété "IsLoaded" permettant de savoir si la ou les entités connexes sont chargées.

using (Modele bdd = new Modele())
{
var requete = from publication in bdd.Publication select publication;

requete.ToList().ForEach((Publication p) =>
{
if (!p.EditeurReference.IsLoaded)
p.EditeurReference.Load();

Console.WriteLine(" Editeur : ID = {0} Nom = {1}", p.Editeur.Id, p.Editeur.Nom);

if (!p.Auteur.IsLoaded)
p.Auteur.Load();

p.Auteur.ToList().ForEach(a => Console.WriteLine(" Auteur : ID = {0} Nom = {1} {2}", a.Id, a.Prenom, a.Nom));
});
}

Aucun commentaire: