Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Bonnes fêtes de fin d'année !

La trève des confiseurs est un rituel sacré, au sens propre pour certains, au sens purement laïc et festif pour les autres. Que vous fassiez partie des premiers ou des seconds, je vous souhaite d'excellentes fêtes de fin d'année.

L'année qui s'achève a été riche en annonces. L'année 2008 qui va s'ouvrir sera l'une des plus exitantes dans notre métier, l'année de LINQ, de l'Entity Framework, de Silverlight, de Astoria (Adot.net data services), de Blend 2.0, et de toutes ces nouveautés extraordinaires ! Vivement 2008 !

Passez de bonnes fêtes !

 

Multithreading simplifié

Le multithreading c'est l'épouvantail du développeur. Vous en parlez, hop! tout le monde s'en va de la machine à café... et s'il y en a un qui ne part pas , c'est le genre fanatique qui va débaler une science opaque sur les AppDomains, les mutex et autres mots qui fâchent, du coup, c'est vous qui partez :-)

Je carricature à peine...

C'est tout le problème du multithreading. Pratiqué avec simplicité c'est une technique de plus en plus indispensable pour tirer partie des microprocesseurs multicoeurs et fluidifier les interfaces, mais voilà, comment faire simple avec une telle technique ?

Les puristes vous diront qu'il faut absolument comprendre la technique, et qu'en suite c'est facile... Un peu comme Coluche qui expliquait dans l'un de ses sketchs que son professeur de violon lui avait dit d'apprendre à jouer avec des gants de boxe parce que quand on les enlève ça semble facile...

Je ne vais pas vous dire qu'une démarche rigoureuse est inutile, j'ai un module de multithreading avancé dans mes plans de cours et, bien entendu, voir les choses en profondeur au sein d'une formation est le seul moyen de maîtriser cette technique. Mais il existe aussi des façons simples d'introduire un peu de multitâche dans vos applications.

Il s'agit du composant BackgroundWorker des Windows Forms. Certes le sujet tranche avec mes billets généralement plus orientés vers les super nouveautés hypra fraîches à tel point qu'elles sont même parfois en bêta... Mais il faut bien maintenir les applications existantes, les améliorer, et pour cela il existe, comme le BackgroundWorker des solutions pratiques qui ne nécessitent pas d'installer le framework 3.5 puisque cette classe a été fournie avec .NET 2.0.

De plus, ce composant Windows Forms n'impose pas de connaître les mécanismes du multithreading, il suffit de programmer ces événements comme un bouton. Trop facile ? Peut-être que cela choquera les puristes parce que "cela cache la réalité de ce qui se passe vraiment dans la machine", je leur répondrais que faire du C# au lieu de faire de l'assembleur c'est un peu pareil... Là où je les rejoindrais c'est que, bien entendu, la classe backgroundWorker ne doit pas être utilisée à tord et à travers. Si l'on désire concevoir des classes gérant finement le multitâche, il faut réellement comprendre et donc apprendre. Mais dans de nombreux cas, le BackgroundWorker pourra vous être utile et rendre plus fluide vos applications Windows Forms sans avoir à entrer dans les détails d'une technique un peu aride.

Mais trève de mots, le plus simple c'est de jouer avec ce composant pour se rendre compte de son utilité. Pour facilité la.. tâche... je vous ai préparé un petit projet VS 2005 qui montre comment se servir de backgroundWorker : BGW.zip (41,83 kb)

Un peu de douceur multitâche dans ce monde de multicoeurs...

Présentation des différentes facettes de LINQ (article à télécharger)

Le voilà enfin ! [Updated ! Version 1.1 en ligne]

un PDF de 32 36 pages et 5 6 projets exemples sous VS 2008 pour vous présenter les différentes facettes de LINQ. Je n'en voyais plus le bout de cet article ! Non par lassitude, bien au contraire, mais parce que LINQ est d'une incroyable richesse et que je voulais vous en dire la maximum.

Sans entrer dans les détails trop techniques de la syntaxe (la doc Microsoft est très complète et n'a nul besoin d'une redite), cet article présente le pourquoi et le comment de LINQ au travers d'explications et d'exemples de code.

  • LINQ to Objects
  • LINQ to SQL
  • LINQ to Dataset
  • LINQ to XML
  • LINQ to Entities

Sans prétendre que toutes ces versions de LINQ n'auront plus de secret pour vous après avoir lu l'article, vous en saurez certainement plus pour mieux comprendre pourquoi il y a eu un avant LINQ et qu'il va y avoir un après LINQ...

Pour télécharger l'article cliquez ici !

Avant de lire cet article il est préférable de connaître les nouveautés syntaxiques de C# 3.0, si ce n'est pas votre cas vous pouvez télécharger mon précédent article.

Pour la liste de tous mes billets sur LINQ cliquez ici.

Note de la version 1.1 : table des matières ajoutée + plus de détails sur Linq to Entities et un projet utilisant la bêta 3.

LINQ à toutes les sauces !

Je suis en train de boucler mon article de présentation de LINQ. Au départ je pensais m'en sortir en une dizaine de pages, mais j'en suis à plus du double... juste pour faire le tour des principales possibilités et sans détailler la syntaxe (ce n'est pas le but de cet article).

J'ai eu maintes fois l'occasion de vous dire ici que LINQ est l'innovation la plus fantastique que j'ai vue depuis longtemps dans un langage. Vous en saurez plus en lisant le prochain article qui sera en ligne ce week-end, mais pour vous prouver que LINQ peut servir partout et tout le temps voici deux exemples à contre-courant de l'idée qu'on se fait des utilisations possibles de LINQ :

Cas 1 : Lister les services actifs de Windows.

C'est bête mais balayer et filtrer une simple liste comme celle là (et de bien d'autres du même genre retournées par le framework .NET ou par vos applications), c'est produire du code pas très marrant... Avec LINQ ça devient :

using System.ServiceProcess; 
var srv = from s in ServiceController.GetServices()
         where s.Status == ServiceControllerStatus.Running
         select s.DisplayName;
ListBox1.DataSource = srv.ToList();

 
Je trouve ça élégant, pas vous ?

Cas 2 : Remettre à unchecked tous les Checkbox d'une form

Balayer certains contrôles d'une fiche n'est là non plus pas l'endroit où l'on s'attend à trouver du LINQ... Et pourtant ! Imaginons une fiche de saisie avec des tas de checkbox et un bouton "raz" de remise à zéro de la fiche. Balayer tous les contrôles de la fiche pour ne sélectionner que les checkbox n'est pas un code bien complexe mais avec LINQ ça devient tellement plus chouette !

var cb = (from Control c in this.Controls select c).OfType<CheckBox>();
foreach (var c in cb) c.Checked=false;
 

C'est pas plus joli et plus clair écrit comme ça ? (et encore on pourrait se passer de la variable "cb" et intégrer directement la requête LINQ après le "in" du "foreach")?

Bref, LINQ j'adore. Et j'espère bien que le papier à venir va vous transformez en fans vous aussi ! alors... Stay tuned !

Les nouveautés syntaxiques de C# 3.0

Les expressions Lambda vous connaissez ?

Et l'inférence des types locaux, les méthodes d'extension, les expressions d'initialisation des objets ou les types anonymes ?

Si tout cela sonne bizarrement à vos oreilles, n'hésitez plus une seconde : téléchargez le nouvel article que j'ai mis en ligne gratuitement !

Voici le lien, il n'y a qu'à cliquer ici !

Vous êtes encore là ?

... Alors ne loupez pas le tout dernier article "Présentation de LINQ avec C#", un papier de 32 pages riche en exemples !

Kit gratuit d'entraînement pour Visual Studio 2008 et le framework 3.5

Microsoft a mis en téléchargement public un kit d'entraînement pour VS 2008 et le framework 3.5.

Le fichier pèse environ 120 Mo, vous pouvez le télécharger en cliquant ici.

Le contenu

Ce training kit est en fait le contenu de formation qui a déjà été donnée sur 5 jours à un certain nombre de partenaires Microsoft ces mois derniers. Il contient 20 hands-on-lab, 28 présentations et une vingtaine de démos scriptées pour se former au produit et à ses nouveautés.

Le contenu a été mis et jour pour refléter la réalité de la version finale (distribuée aux abonnées MSDN depuis ce mois-ci en attendant la mise sur la marché en février prochain - vous pouvez donc utiliser la bêta 2 en téléchargement gratuit dans ce laps de temps si vous n'êtes pas abonné MSDN).

Les sources d'info complémentaires

Le petit supplément de Monsieur Plus : je vous rajoute en prime les liens de plusieurs vidéos complémentaires au kit :

Rien que du bon, mais en anglais. Pour les francophiles/phones anglophobes il faudra attendre mes articles à venir.. Alors : Stay Tuned !

SQL Server 2008 et le type FileStream - résumé de la conférence DAT304 des TechEd 2007

Gérer des données "raw" tels que des fichiers multimédia, de la documation, etc, dans une base de données est un sujet qui divise les développeurs depuis longtemps. SQL Server 2008 va (enfin) mettre fin à cette dispute de principe !

DAT304 - Managing Unstructured Data in SQL Server 2008: Introducing the Filestream Datatype

Je n'ai suivi que partiellement cette conférence, il faudra d'ailleurs que je profite de la diffusion en ligne des vidéos pour les participants aux TechEd pour la regarder en totalité. Ce qui m'intéressait c'était l'info elle-même qui se résume à un nouveau type champ dans SQL Server. Mais c'est une avancée de taille, je vais vous expliquer pourquoi en quelques lignes...

Le duel blob vs file system pour les données raw

En effet, il y a d'une côté les tenants du "tout file system" c'est à dire le stockage des fichiers en dehors de la base de données avec juste le stockage des noms de fichiers dans la base elle-même. Pour: la simplicité, la gestion des flux du file sytem généralement plus performante que les blobs. Contre: le manque cruel de consistence, pas de contexte transactionnel, backups à faire séparément, etc, etc. Je fais partie des "anti" d'ailleurs.

De l'autre côté il y a ceux qui préfèrent le stockage en blob. Pour : consistence des données, contexte transactionnel, backup unique, etc. Je pour pour cette solution en général. Contre : les blobs sont moins rapide en lecture / écriture de flux que le file system, certains SGBD imposent des limites à la taille des blobs. Si on fait abstraction de ce dernier argument (il suffit d'utiliser une base n'ayant pas cette limite, par exemple SQL Server 2005 ou même Firebird/Interbase), le léger inconvénient de la rapidité (qui reste modeste et peu gênant dans la plupart des cas) est largement, à mon avis et par expérience, compensé par les avantages de cette technique. Reste qu'on peut faire mieux...

Mélanger le meilleur des deux solutions 

C'est justement ce que propose SQL Server 2008 avec le nouveau type FileStream qui est une extension de VARBINARY(MAX) qui s'en distingue par un attribut lors de la création du champ.

Le principe est simple : on marie le meilleur des deux solutions existantes. On prend la souplesse (gestion des quotas par ex) et la rapidité du file system (NTFS obligatoirement) et on l'associe à la cohérence des données de la solution blob. En gros, SQL Server 2008 stocke les fichiers dans le file system mais assure l'accès à ces fichiers comme à n'importe quel autre champ ce qui permet la gestion transactionnelle, le backup unique et centralisé.

Conclusion 

Une solution simple et performante à un problème de plus en plus crucial, les utilisateurs devant de plus en plus gérer des données lourdes (photos, documents digitalisés, vidéos...) en synchronisme parfait avec les bases de données. Une fichier client peut comporter une photo, une fiche article une vidéo de présentation, tout cela n'est plus "exotique", cela devient une contrainte légitime d'exploitation.

Pour l'instant SQL Server 2008 est en bêta, mais comme son nom l'indique il devrait être bientôt sur le marché...

Encore une bonne idée, ingénieuse et simple à mettre en oeuvre. Je trouve que les équipes de dev de MS ont vraiment l'âme créative depuis qu'on est entré dans ce que j'appelle "l'ére .NET". Souhaitons que ça dure le plus longtemps possible !

A+ pour un nouveau billet. Stay tuned !

DeepFish, votre PDA va ferrer un gros poisson !

Deepfish vous ne connaissez pas encore ?

C'est le futur navigateur Web pour Windows Mobile de Microsoft. Il fonctionnera donc sur toutes les plateformes mobiles acceptant l'OS Microsoft, PDA, Smartphones, ou Pocket PC's.

La grande nouveauté dans ce produit n'est pas juste de pouvoir naviguer, ce qu'on peut déjà faire avec la plupart des machines mobiles sous Windows Mobile. La véritable innovation c'est qu'on peut surfer sur tous les sites web en voyant la page exactement comme on la verrait sous IE ou Firefox sur un PC "normal", donc sur tous les sites du Web de la planète !

Fini la programmation spéciale des sites Web pour être utilisables par des unités mobiles ! C'est un grand pas en avant, une solution élégante à un problème jamais résolu. On se souviendra de l'échec du WAP par exemple dont les SSII parisiennes chantaient les louanges à chaque client dans l'espoir de décrocher des contrats.. C'était juste avant l'explosion de la "bulle internet"...

Terminé donc les fausses solutions coûteuses. Seul hic à la solution Deepfish, à mon sens, c'est que toutes les requêtes internet doivent passer par un proxy Microsoft pour être traitées. C'est là en effet que se cache l'astuce de Deepfish : toutes les pages sont prétraitées par ce proxy qui les retaille pour qu'elles s'affichent sur votre PDA comme sur un PC. Combien de proxies MS va-t-il installer dans le monde pour que le système reste fluide ? D'autres sociétés auront-elles le droit de proposer leurs propres proxies sur la même technologies ? Quid de la confidentialité des requêtes centralisées par le proxy ? Deepfish n'est encore qu'une bêta et ces questions trouveront certainement réponses naturellement dans les mois à venir. Je n'ai pas non plus balayé 100% des sites MS sur le sujet et peut-être certains lecteurs de ce billet savent-ils des choses que j'ignore. Dans ce cas, n'hésitez à compléter l'info en laissant un commentaire, c'est aussi fait pour ça !

Une petite vidéo sur Youtube montrant Deepfish à l'oeuvre sur un petit portable :


P1000844_xvid
envoyé par edupin

Une autre vidéo créée par le labo MS de SupInfo (Lire leur billet sur Deepfish)

Présentation de Deepfish

Bon (micro) surf sur votre smarphone !

Entity Framework Application Patterns. Résumé de la conférence DAT303 Teched 2007

Hier je vous ai résumé la conférence DAT201 qui présentait l'Entity Framework. Aujourd'hui je vous parlerai plus brièvement d'une autre conférence. Cette brièveté du résumé ne doit pas vous induire en erreur : la conférence DAT303 de Pablo Castro, Technical Lead, est peut-être la meilleure à laquelle j'ai assitée.

D'abord Pablo est un jeune gars sympa. Ensuite malgré un fort accent cubain ou mexicain il a soutenu une conf à un rythme d'enfer tout en étant d'une grande clareté, une vraie conf technique comme je les aime, faite par un passionné qui connaît son affaire. Enfin, cette conférence dépassait le cadre de la présentation générale pour parler vrai et pratique. Là, Pablo m'a appris des choses sur l'Entity Framework. Des trucs pas simples à découvrir tout seul, une conférence qui fait vraiment gagner du temps et de la compétence. Merci Pablo !

Si le résumé sera court c'est que 95% de la conférence de Pablo était basée sur du code. Vous imaginez bien qu'il n'était pas possible de prendre le tout en sténo dans la pénombre de la salle de conf... J'ai revisionné aujourd'hui la conf (puisque toutes les sessions principales ont été filmées), et franchement même assis dans mon bureau à l'aise il nétait pas possible de noter la totalité des manips, toutes essentielles. J'ai d'ailleurs demandé à Pablo s'il pouvait avoir la gentillesse de m'envoyer le code source de ces démos, et s'il accèpte je les mettrais en téléchargement ici.

Donc de quoi s'agissait-il ?

Bien entendu de l'Entity Framework, depuis mon billet d'hier vous devez savoir de quoi il s'agit (sinon foncez lire ce dernier, ne vous inquiétez je ne bouge pas, vous pourrez revenir ici plus tard :-) ).

Mais il n'était plus question ici de parler en général ou même en détail du fonctionnement de EF, il s'agissait de voir comment s'en servir "en vrai" dans trois conditions :

  • En 2 tiers
  • Dans une application Web
  • Au sein d'une architecture 3-tiers

En effet, le principal problème de toute surcouche est de manger un peu plus de CPU et de mémoire que la couche du dessous. C'est la règle en informatique, plus c'est pratique et puissant, plus la machine doit pédaler. Et même si EF est très efficace et très optimisé, ce qu'il fait en plus possède forcément un coût. Il est donc essentiel de pouvoir maîtriser ce coût en faisant des économies là où cela est possible.

La bonne nouvelle c'est que EF le prévoit et que la mise en oeuvre est simple. La moins bonne nouvelle c'est que la chose devient un poil plus "mystique" et qu'il faut réfléchir un peu plus. Mais un informaticien paresseux des neurones est soit en chômeur en puissance, soit un ex-informaticien au RMI...

Change tracking et Identity resolution

Deux mécanismes peuvent être économisés (et les ressources CPU/RAM qui vont avec) : Le change tracking et l'identity resolution. Le premier, détection des changements, permet à l'EF de savoir quels objets ont été modifiés pour savoir comment appliquer les mises à jour à la base de données. Si certaines entités (ou grappes d'entités) ne seront pas modifiées on peut alors se passer du mécanisme de détection des changements... L'identity resolution, ou résolution des identités est utilisée pour identifier de façon formelle toutes les instances des entités. Il est en effet primordial pour le système de savoir à quel(s) enregistrement(s) de la base de données corespond(ent) l(es) entité(s) sinon il est impossible d'envisager des fonctions comme le refresh, l'update ou le delete...

Heureusement EF est très bien conçu et il est possible de stopper ces mécanismes là où on le désire. Ce court billet (qui devient déjà long...) n'entrera pas dans les détails, je prépare un article sur la question, format plus adapté à un long exposé technique avec exemples de code.

Des entités qui passent les frontières... 

Un autre problème se pose, notamment dans les applications en multi-tiers : lorsqu'une instance d'entité est passée en dehors du système, EF en perd la trace... Imaginons un serveur applicatif qui utilise EF pour accéder à une base de données afin d'offrir des services de type WCF (ex remoting, pour simplifier) ou même des services Web. Les changements dans les objets ont lieu en dehors même de la machine qui utilise EF. Le lien est cassé et si l'objet revient au serveur applicatif qui doit en retour mettre à jour la base de données, EF ne le connaîtra plus et ne pourra pas l'intégrer à son mécanisme de mise à jour de la base.

Là encore EF permet de contourner le problème. La façon de le faire sera aussi décrite dans le papier en cours de préparation, soyez patients !

Compilation LINQ 

Enfin, Pablo a montré comment économiser des ressources du côté de LINQ cette fois-ci en utilisant la possibilité de compiler la requête sous la forme d'un delegate qu'il suffit ensuite d'appeler. L'utilisation des expressions Lambda et l'utilisation des interfaces idoines permettent même d'avoir une requête compilée mais paramétrique dont le résultat peut être réutilisé dans une autre requête LINQ. Pas de magie, et peu de code à taper pour réaliser tout cela. En revanche, une fois encore, cela ne s'improvise pas si on ne connaît pas l'astuce.

Conclusion

Une conférence riche, dense et instructive. Je pourrais en parler encore des pages entières mais sans la contrepartie du code exemple et des explications qui vont avec ce billet deviendrait vite ennuyeux. Je préfère m'arrêter là et réserver les détails d'implémentation pour l'article que je prépare sur ce sujet. Bien entendu il sera annoncé ici et sera téléchargeable gratuitement comme d'habitude.

Une dernière chose, Pablo nous a fait voir un peu Astoria, un procédé permettant d'exposer une (partie d'une) base de données en HTTP dans un formalisme XML. Une sorte de Web service généré automatiquement pour chaque classe et qui, par des GET ou des POST permet d'accéder aux données mais aussi de mettre à jour les données dans un mécanisme de type accès à une page Web ! Je n'ai pas eu le temps de creuser la question ni de faire tourner de bêta de Astoria, mais soyez sûrs que dès que j'en aurais fini avec mon tri de toutes les conférences des TechEd, Astoria sera au programme !

Plein de nouveautés encore à venir, so, stay tuned !

 

Entity Framework - Résumé de la session DAT201 aux TechEd 2007

Cette conférence était l'une de celle que j'attendais le plus. De ce que j'avais déjà vu de LINQ et de ce qui tournait autour de cette nouveauté du framework 3.5 je savais qu'il y avait là un joyau... Les quelques essais que j'avais faits avec la Bêta de VS 2008 n'avaient qu'attisé ma curiosité. Je désirais donc à tout prix voir la session DAT 201 : Entity Framework Introduction pour refaire le tour complet de la technologie pour être sûr de ne pas passer à côté d'un élément essentiel.

Et c'est encore mieux que ce que je pensais. C'est une pure merveille, une avancée aussi spectaculaire que la naissance du framework .NET lui-même. Rien de moins.

L'Entity Framework

La session DAT 201, présentée par Carl Perry, Senior Program Manager Lead chez Microsoft, se voulait une introduction, un tour du propriétaire de l'Entity Framework. Mais kesako ? Le "cadre de travail pour entité" en français. Avec ça vous êtes bien avancé !

Pour faire le plus court possible disons que l'EF (Entity Framework) est une nouvelle couche d'abstraction se posant sur ADO.NET et permettant tout simplement d'accéder aux données de façon totalement objet et surtout dans le respect d'un schéma conceptuel et non plus en travaillant avec la base de données, son schéma physique et son SQL.

Est-ce que vous êtes plus avancé ? j'ai comme un doute... Mais les choses vont s'éclaircir avec la suite de ce billet.

Pour mieux comprendre la différence ne serait-ce que dans le code, comparons les deux types d'accès aux données, ADO.NET 2.0 et EF.

L'accès aux données de ADO.NET 2.0

Voici un code typique d'accès aux données via ADO.NET 2.0 tel qu'on en voit dans toutes les applis ou presque :

On retrouve toute la chaîne d'opérations usuelles, de la création et l'ouverture de la connexion jusqu'à l'itération dans le resultset retournée par le DataReader suite à l'envoi d'une Command dont le contenu est du pur SQL exprimé dans le dialect spécifique de la base de données cible.

Cette méthode est puissante, souple, mais elle possède de nombreux pièges. Par exemple l'accès aux données du DataReader s'effectue par les noms de champ. Une simple coquille à ce niveau et le bug ne sera détecté qu'à l'exécution, peut-être dans 6 mois chez le client quant il utilisera cette fonction particulière du logiciel. Le coût de cette coquille peut être énorme s'il s'agit d'un logiciel diffusé en grand nombre (hot line de maintenance, détection du bug - pas toujours simple, création d'une mise à jour - les sources elles-mêmes ont bougé, problème de versionning, diffusion de la mise à jour et découverte de nouveaux problèmes - incompatibilités d'une des modifications, etc, etc). J'arrête là le scénario catastrophe car selon les lois de murphy je suis encore en dessous de la réalité, et vous le savez comme moi...

Le pire c'est que je n'ai relevé qu'une seule des erreurs possibles, ce code possède bien d'autres pièges qui agiront comme des aimants à bugs ! Un autre exemple, toujours sur l'accès aux données lui-même : Il n'y a aucun contrôle de type. Je passe sur les conséquences que vous pouvez imaginer dans certains cas.

Car il y a plus grave encore : pour obtenir les données il faut taper un ordre SQL spécifique à la base cible... D'une part cela n'est pas portable, d'autre part ce n'est que du texte pour le compilateur. On écrirait "coucou" à la place de l'ordre SELECT ça compilerait tout aussi bien.

Je ne vous refais pas l'énumération des problèmes en cas de coquille (fort probable) dans une longue chaîne SQL. Je vous épargnerais aussi la liste des ennuis si l'admin de la base de données change le nom d'un champ ou le type de l'un d'entre eux ou s'il réorganise une table en la coupant en 2 ou 3 autres pour des raisons d'optimisation. C'est tout le soft qui devra être corrigé à la main sans rien oublier.

Bref, aussi génial que soit le framework .NET, aussi puissant que soit ADO.NET, on en était encore au même style de programmation des accès aux données que ce que ADO Win32 ou dbExpress chez Borland avec Delphi permettaient. Une logique proche, collée devrais-je dire, au schéma physique de la base de données et totalement inféodée à son dialect SQL, le tout avec des accès non typés aux données.

Certes ADO.NET 2.0 permettait d'aller un cran plus loin avec la génération des DataSet typés sous VS 2005. Une réelle avancée, mais qui n'était qu'un "arrangement" avec le modèle physique.

L'accès aux données avec ADO.NET Entity Framework

Dans cet exemple (qui fait exactement la même chose que le précédent) et dont nous comprendrons plus loin les détails on peut distinguer plusieurs choses :

  1. Il n'y a plus de SQL, il a disparu.
  2. On ne s'occupe plus de l'ouverture et de la fermeture de la connexion ni même de sa création.
  3. Les données sont interrogées en C#, bénéficiant d'Intellisense et du contrôle syntaxique.
  4. On itère à travers une liste d'objets dont les propriétés sont typées.

Non, ne cherchez pas l'astuce de ce côté là... si si, vous vous dîtes "le SQL a été tapé ailleurs il est simplement caché maintenant". Non. Dans cette façon d'accéder aux données personne n'a tapé de SQL, personne n'a créé de connexion à la base. Enfin, si, quelqu'un s'est chargé de tout cela de façon transparente : l'Entity Framework.

L'évolution dans les accès aux données

 

Sur le schéma ci-dessus on voit en colonne, respectivement : le niveau d'abstraction, le langage d'interrogation et le résultat des requêtes. En ligne nous trouvons ADO.NET 2.0 et, en dessous, ADO.NET EF.

  • Le niveau d'abstraction de ADO.NET 2.0 est de type bas niveau, c'est à dire qu'il colle au schéma de la base de données (le modèle physique, le MPD).
    Le niveau d'abstraction de EF change totalement puisqu'ici on travaille en haut niveau, celui du schéma conceptuel (le MCD).
  • Côté langage d'interrogation, ADO.NET repose sur le dialecte SQL de la base cible exprimé sous la forme de chaînes de caractères dans le code.
    De son côté EF offre LINQ, ou Requêtage intégré au Langage (Language-Integrated Query) totalement indépendant de la base cible.
  • Enfin, pour les résultats des requêtes, ADO.NET offre un accès non typé source d'erreurs, là où EF offre des objets aux propriétés typées.

On le voit ici clairement, le bon technologique est faramineux, c'est bien au niveau d'un modèle conceptuel qu'on va travailler en ignorant tout du modèle physique et du langage de la base de données !

C'est d'autant plus extraordinaire lorsque, comme moi, on commence à avoir quelques heures de vols et qu'on a connu moultes tentatives couteuses et infructueuses chez plusieurs éditeurs de logiciels de créer des couches d'abstraction pour accéder aux données de différentes bases sans modifier l'application... Ce rêve de pouvoir fournir qui sa compatibilité, qui son logiciel de gestion médical sous SQL Server autant que Oracle ou MySQL en configurant juste l'application mais sans la recompiler ni même en maintenir plusieurs versions, ce rêve est aujourd'hui une réalité, une extension naturelle de .NET !

Pour l'instant tout ceci se trouve au niveau du développeur mais il semble évident qu'on puisse pousser la logique au niveau de l'utilisateur. J'y suis particulièrement sensible puisque, vous le savez certainement, je suis l'auteur et l'éditeur de MK Query Builder, un ensemble de composants permettant à l'utilisateur final d'interroger librement les données d'une application (il s'agit de ce qu'on appelle un requêteur visuel ou Visual Query Builder). Quand je vois le temps, le code nécessaire pour offrir modestement à mon niveau les fonctionnalités avancées de MKQB aux utilisateurs finaux, je ne peux que rester admiratif et ressentir un respect immense pour l'équipe Microsoft qui a développée LINQ et l'Entity Framework !

L'Entity Data Model (EDM)

L'EDM est le schéma conceptuel des données dans EF. C'est un vocabulaire qui décrit le schéma conceptuel pour être exact. Visual Studio 2008 le représente graphiquement sous forme d'entités et de liens comme un diagramme de classe.

Il permet au développeur de fixer le cadre des données qu'il souhaite voir, conceptuellement et sans rapport direct avec le schéma physique de la base de données.

EDM représentent d'une part les entités et des relations.

Les entités sont des types distincts (des classes) qui possèdent des propriétés qui peuvent être simples (scalaires) ou complexes. Les relations décrivent pour leur part la façon dont les entités sont liées. Il s'agit d'une déclaration explicites des noms de relation et des cardinalités.

Mais quand met-on les mains dans le camboui ? Il faut bien qu'à un moment ou un autre ce modèle conceptuel puisse correspondre avec le schéma de la base de données... Oui, bien entendu, mais une fois encore, pas de bas niveau ici.

Le schéma EDM peut être créé et modifié totalement graphiquement par le développeur (sous VS 2008) mais ce dernier possède aussi le moyen de faire le mapping entre les entités "idéales" de EDM et les entités physiques de la base de données. Pour cela deux façons coexistent : la plus simple consiste à faire un drag'n drop entre l'onglet des connexions SGDB de VS 2008 et l'espace de travail du schéma EDM ! On prend des tables, on les pose, et le schéma s'écrit de lui-même, relations comprises.

Par exemple la pattern courante "many to many" qui relie une table de lycéens à la table des options suivies par chacun fait intervenir une troisième table dans le schéma physique, celle qui contient les paires de clés lycéen/option. Ainsi un lycéen peut suivre plusieurs options et une option peut être suivies par plusieurs lycéens. Un classique des classiques. Cette pattern est détectée par EDM qui créé automatiquement une jointure n-n entre les deux entités, comme dans le schéma conceptuel de la base de données.

EDM automatise ainsi 95% de la création du schéma conceptuel, même si celui-ci ressemble encore beaucoup au modèle physique de la base. C'est là qu'interviennent les 5% restant : le développeur peut à sa guise supprimer ou ajouter des champs, des relations, et il indique explicitement à EDM comment les mapper sur les tables existantes dans la base de données.

Prenons l'exemple d'une base de données correctement optimisée et standardisée. Une fiche client pouvant posséder une adresse de livraison et une adresse de facturation, le concepteur de la base à séparer les deux informations. On a d'une part une table des clients et de l'autre une table des adresses plus deux jointures AdresseFacturation et AdresseLivraison qui parte de Client vers Adresse avec une cardinalité 0..1/1..1, c'est à dire qu'un client peut posséder 0 ou 1 adresse de facturation, 0 ou 1 adresse de livraison et que chaque adresse doit correspondre à 1 et 1 seul client (si on ajoute un type dans Adresse pour indiquer Facturation ou Livraison, le MCD pourra d'ailleurs exprimer la cardinalité sous la forme d'un lien dit identifiant avec Client).

Sous EDM, si on place les tables par drag'n drop, par force on trouvera dans le schéma les deux entités Client et Adresse avec ses liens. Toutefois cela n'est pas réellement intéressant. D'un point de vue conceptuel nous allons travailler sur des fiches Client, et ses fiches possèdent une adresse de livraison et une autre de facturation. Pour nous, conceptuellement, ces adresses ne sont que des propriétés de Client. On se moque totalement des problèmes d'optimisation ou des règles de Codd que l'admin de la base de données a ou non suivi pour en arriver à créer deux tables... Cela appartient au modèle physique et nous ne voulons plus nous embarrasser de sa lourdeur et de son manque de pertinence conceptuelle.

Le développeur peut alors ajouter à Client deux propriétés, AdresseFacturation et AdresseLivraison, qui seront des propriétés complexes (retournant une fiche Adresse). Il supprimera aussi l'entité Adresse du schéma et enfin indiquera à EDM le mapping de ces deux nouveaux champs.

A partir de maintenant l'application pourra obtenir, trier, filtrer, des instances de Client qui possèdent, entre autres propriétés, une adresse de livraison et une autre de livraison. Plus aucun lien avec le schéma de la base de données, uniquement des choses qui ont un sens du point de vue conceptuel. C'est EF qui s'occupera de générer les requêtes sur les deux tables pour créer des entités Client.

Cela fonctionne aussi en insertion et en mise à jour... Le rêve est bien devenu réalité. Mieux, on peut personnaliser les requêtes SQL (en langage de la base cible) si vraiment on désire optimiser certains accès. De même on peut utiliser des procédures stockées au lieu de table ou de vues, etc.

L'aspect purement génial de EF c'est qu'il offre un mode automatique totalement transparent pour travailler au niveau conceptuel sans jamais perdre la possibilité, à chaque niveau de sa structure, de pouvoir intervenir manuellement. Qu'il s'agisse des entités, de leur mappings, des relations autant que la possibilité de saisir du code SQL de la base cible. Certes ce genre de choses n'est absolument pas à conseiller, en tout cas pour l'écriture manuelle de SQL, c'est un peu un contre emploi de EF... Mais que la possibilité existe montre surtout l'intelligence de la construction de EF qui n'est pas une "boîte noire" sur laquelle il est impossible d'intervenir et qui, par force, limiterait les possibilités dans certains cas.

Interroger les données

Pour interroger les données, EF nous donne le choix entre deux méthodes :

LINQ to Entities

C'est l'exemple de code donné en début de ce billet. LINQ To Entities est une extension de C# qui possède des mots clés proches de SQL (from, where, select..). Mais soyons clairs : LINQ to Entities permet d'interroger le modèle conceptuel, l'EDM, et non pas la base de données ! C'est le mélange entre LINQ et EDM qui permet à EF de générer lui-même le code SQL nécessaire.

LINQ est d'une extraorinaire puissance. D'abord on reste en C#, on bénéficie donc de Intellisense, du contrôle de type, etc. Ensuite, LINQ to Entities n'est qu'une des émanations de LINQ puisqu'il en existe des variantes comme LINQ to XML qui permet globalement la même chose mais non plus en interrogeant des schémas EDM mais des données XML. Le fonctionnement de LINQ dépasse le cadre de ce billet et j'y reviendrai tellement il y a de choses à en dire.

Entity SQL

Si tout s'arrêtait là, Entity Framework serait déjà énorme. J'en pers un peu mes superlatifs tellement je trouve le concept et son implémentation aboutis. Je suis un fan de EF et de LINQ, vous l'avez remarqué et vous me le pardonnerez certainement une fois que vous l'aurez essayé...

Mais en fait EF propose un second moyen d'interroger les données, la tour de babel SQL, c'est à dire Entity SQL.

Il existe en effet de nombreux cas où LINQ pourrait s'avérer plus gênant que génial. Par exemple dans certains cas où le requêtage doit être dynamique (la requête est construite en fonction de choix de l'utilisateur, un écran de recherche multicritère par exemple). Décrocher de EF pour ces cas (pas si rares) imposerait de revenir à du SQL spécifique de la base cible, écrit dans des strings non testables, recevoir des données non typées, créer et gérer des connexions à la base en parallèle de LINQ utilisé ailleurs dans le code, et plein d'autres horreurs de ce genre.

Heureusement, Entity SQL existe. Il s'agit d'un langage SQL spécial, universel dirons-nous, qui ajoute la sémantique EDM à SQL. Ce SQL là est spécial à plus d'un titre donc. Le premier c'est qu'il permet d'interroger l'EDM, le modèle conceptuel, comme LINQ, mais en SQL. Le second c'est que ce SQL "comprend l'objet" et sait utiliser non pas des tables et des champs mais des entités et des propriétés. Enfin, il est universel puisque lui aussi, comme LINQ, sera traduit par EF en "vrai" SQL de la base cible. Le même code Entity SQL fonctionne donc sans modification ni adaptation que la base soit Oracle, MySQL ou SQL Server !

Le rêve de certains éditeurs de logiciels dont je parlais plus haut s'arrêtait d'ailleurs là : créer un SQL interne à l'application qui serait traduit en SQL cible par un interpréteur lors de l'exécution. L'un des projets comme celui-là qui me reste en tête à coûté une fortune pour ne jamais marcher correctement... Entity SQL lui fonctionne de façon performante et s'intègre à Entity Framework ce qui permet de bénéficier de l'abstration conceptuelle et de l'environnement objet. La réalité dépasse largement le rêve.

La traduction des requêtes

Toutes les requêtes sont exécutées par la base de données. Je le sous-entend depuis le début mais c'est mieux de le (re)dire pour qu'il n'y ait pas de méprise...

Les requêtes LINQ et Entity SQL sont transformées en requêtes SQL de la base cible par Entity Framework grâce à l'EDM qui contient la description des entités, des jointures et du mapping.

LINQ et eSQL fonctionnent sur le même pipeline de requêtag. Il transforme les constructions de EDM en tables, vues et procédures stockées. Ce socle commun est basé sur un modèle de fournisseurs qui autorise la traduction vers différents dialectes SQL (donc des bases cibles différentes).

EntityClient, le fournisseur d'accès aux données de EF

"N'en jetez plus !" pourraient s'écrier certains... Et oui, ce n'est pas fini. En effet, et comme je le soulignais, Entity Framework permet d'intervenir à tous les niveaux, du plus haut niveau d'abstraction au plus bas, dans la cohérence et sans pour autant être obligé de faire des choix ou se passer de tel ou tel avantage.

On a vu que par exemple on pouvait injecter du SQL cible dans le modèle EDM, même si cela n'est pas souhaitable, c'est faisable. On a vu qu'on pouvait préférer eSQL à LINQ dans certains cas. De même on peut vouloir totalement se passer de l'objectivation des entités pour simplement accéder aux données de façon "brutes" mais sans perdre tous les avantages de EF.

Pour ce cas bien particulier EF propose un fournisseur de données appelé EntityClient. Il faut le voir comme n'importe quel fournisseur de données ADO.NET. Il propose le même fonctionnement à base d'objets Connexion, Command et DataReader. On s'en sert comme on se sert d'un fournisseur SQL Server ou OleDB sous ADO.NET 2.0.

Toutefois, EntityClient interroge lui aussi le schéma conceptuel, l'EDM. Le langage naturel de ce provider d'accès est eSQL (Entity SQL) présenté plus haut.

Utiliser EntityClient peut s'avérer utile lorsque l'application n'a pas du tout besoin d'objets, ou lorsqu'elle possède sa propre couche objet (business object layer par exemple) qu'elle souhaite alimenter sans passer par les instances d'entités de EF tout en bénéficiant de l'abstraction de EF (utiliser un SQL universel notamment).

Les métadonnées

L'Entity Framework fournit un service d'accès aux métadonnées. Il s'agit d'une infrastructure commune permettant de décrire le stockage, le modèle, et la structure des objets, les procédures stockées, les informations de mapping et même les annotations personnalisées.

L'API publique permet de créer et d'utiliser des MetadataWorkspace directement, d'obtenir des MetadataWorkspace depuis des ObjectContext, d'utiliser les métadata retournées par les enregistrements de données de EntityClient.

Conclusion

La présentation de Carl Perry était entrecoupée de quelques démos permettant bien entendu de mieux voir et comprendre les concepts exposés. Visual Studio 2008 permet d'utiliser l'Entity Framework de façon simple et naturelle, le voir est toujours préférable à le croire sur parole. En tant que témoin de la session, et ayant "joué" avec la bêta de VS 2008 bien avant et étant depuis hier comme tous les abonnés MSDN l'heureux possesseur de la version finale de VS 2008, je peux vous certifier que tout ce que j'ai dit ici est.. en dessous de la vérité ! Testez vous-mêmes Entity Framework et vous comprendrez à quel point les temps ont changé, vous sentirez par vous-mêmes ce fantastique bond technologique qui relègue toutes les autres tentatives de ce type ou approchant (comme ECO de Borland par exemple) au rang des antiquités d'un autre millénaire... Entity Framework c'est une claque aussi forte que la sortie de .NET lui-même, on ne programmera jamais plus après comme on le faisait avant..