Entity Framework 4.0 et SQL Server CE

11. juin 2010

Je viens de faire le portage de UrzaGatherer depuis SQL Server 2008 R2 Express vers SQL Server CE 3.5 SP2.

Plusieurs choses sont bonnes à savoir pour que ce genre de portage se passe bien:

Le provider SQL Server CE pour Entity Framework 4.0 ne supporte pas la génération automatique des clefs il faut donc se faire une petite requête pour les générer:

Card card = new Card();
card.ID = (from c in Tools.Entities.Cards select c.ID).Max() + 1;

 

Les requêtes LINQ avec des jointures sont très mal supportées. Par exemple, ce genre de requêtes est extrêmement lent:

 var query = from card in Tools.Entities.Cards
     join blk in Tools.Entities.Blocks on card.Expansion.BlockID equals blk.ID
     where (expansionID == 0 || card.ExpansionID == expansionID) && 
(blockID == 0 || blk.ID == blockID) select card.Expansion.Name; expansionsCount = query.Distinct().Count();

La version suivante donne le même résultat mais avec un gain de performances de l’ordre de 20:

var query = from card in Tools.Entities.Cards                            
            where (expansionID == 0 || card.ExpansionID == expansionID) 
&& (blockID == 0 || card.Expansion.BlockID == blockID) select card.ExpansionID; expansionsCount = query.Distinct().Count();

Les comparaisons de chaines sont un peu hasardeuses. Par exemple le code suivant provoque un bug:

 from card in expansion.Cards
 where
    (card.Color.Name == filterColor || filterColor == " ")                     
 select card;

Le provider dans ce cas la se prend un peu les pieds dans le tapis et considère que la chaine filterColor doit faire une longueur de 1 (à cause du “ “). Il faut donc évaluer au préalable la valeur de test:

 bool enableColorFilter = filterColor != " ";

 return from card in expansion.Cards
            where
                   (card.Color.Name == filterColor || !enableColorFilter)
            select card;

Il faut aussi tenir compte du fait que le Skip() et le Take() ne sont pas gérés.

Pour le reste, le provider s’en sort très bien et le résultat est excellent.

Bookmark and Share

.Net

10 trucs sur ma vie

10. juin 2010

Alors, j’avais vu, il y a un bail,  un blog sympa sur le site de Mitsu et je relance l’idée. Le but du jeu est de donner 10 vérités (anodines ou pas) sur soi-même puis de passer le relais à un ami qui devra faire de même et ainsi de suite.

Donc je me lance:

  1. Mon nom se prononce “KA TU EUUUUH” et non pas “KA TU”. En effet, dans les Landes d’où je suis originaire, on prononce le “HE”. Sauf que pour les esprits simplistes de la ville, j’ai simplifié
  2. Ma couleur préférée est le noir car j’adore le concept que l’absence de couleurs est une couleur (Il parait que cela amincit mais il n’y a pas de rapport)
  3. J’ai un “PI” tatoué sur le bras droit en hommage aux mathématiques qui me rassurent en expliquant notre univers
  4. Mon alimentation est à 95% basé sur la viande de boeuf (bleu merci)
  5. Je suis un geek de dernier niveau qui joue à Wow, Starcraft2 et qui passe des heures à regarder des séries télé
  6. Si je devais refaire ma vie, je voudrais être neuro-chirurgien pour comprendre notre cerveau et le concept de conscience
  7. Depuis que j’ai un PC (soit depuis 207 ans), je développe sur les outils de Microsoft (oui même sous DOS) d’abord en C, puis en C++ puis en C#.
  8. Depuis que j’ai un PC (soit depuis très longtemps), je développe des moteurs 3D (les premiers sentaient un peu la cire molle mais j’ai progressé depuis)
  9. Je suis fan des discussions mystiques autour des questions de la vie (ou va-t-on? qui sommes-nous? qu’est ce que le vide ou l’infini?)
  10.   J’ai passé une grande partie de ma vie à croire qu’un magasin bien achalandé se comprenait et s’écrivait : “un magasin bien achats landais”. Oui, j’ai honte.

 

Je passe maintenant la balle à Mitch. Mon pote, à toi de jouer :)

Bookmark and Share

Divers

La gloire, les femmes nues et la fortune

7. juin 2010

Mon article sur DirectX11 vient de paraitre dans le “Programmez” de ce mois-ci. Je suis donc officiellement célèbre :).

N’hésitez donc pas à vous jeter sur le magazine qui est disponible en kiosque pour savourer (que dis-je, pour vous délecter de) cette saine lecture.

Ah, on me dit que j’en fais trop. Bon ben allez le lire si vous voulez un premier aperçu technique de DirectX 11…

PS : Le lien vers le site de Programmez

Bookmark and Share

DirectX

La team Bewise et la team MS à la BDC 2010

6. juin 2010

Face à tant de beauté, je ne peux que laisser l’image parler:

 

1

Bookmark and Share

Bewise

Vidéo d’utilisation d’UrzaGatherer

6. juin 2010

Un petit exemple d’utilisation rapide d’UrzaGatherer:

Bookmark and Share

UrzaGatherer

Mise à disposition de la base complète UrzaGatherer

6. juin 2010

La base complète avec toutes les images pour UrzaGatherer est désormais disponible.

La petite bête fait actuellement 2.8Go. Ca fait un gros beef steak à télécharger. Le tout est disponible ici:

http://www.catuhe.com/urzagatherer/urzafull.bak.

Pour installer la base, il est nécessaire d’avoir SQL Server 2008 R2 Express. Par la suite, UrzaGatherer peut installer la base tout seul via une interface qui apparaitra au premier lancement.

Bon téléchargement :)

Bookmark and Share

UrzaGatherer

Le truc à la con du jour : Lancement de plusieurs fenêtres en série dans WPF

4. juin 2010

Un truc bien débile qui m’est arrivé aujourd’hui. Au sein d’une application WPF qui poutre (http://urzagatherer.codeplex.com), je voulais, lors du lancement ouvrir une première fenêtre avant la fenêtre principale.

Le code ressemble donc à ça dans le constructeur de mon App:

            InstallDatabaseWindow databaseWindow = new InstallDatabaseWindow();
            databaseWindow.ShowDialog();

            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();

Rien de bien formidable me direz-vous? Et bien si vous faites un test, vous verrez que le Show sur votre mainWindow.Show() plantera généreusement avec le message suivant:

“Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.”

Bon, au premier abord, je me suis dit que j’ai du merdé dans mon constructeur.

En fait, pas du tout (je me disais aussi que ce n’était pas possible) l’explication est plus sioux : Par défaut, une application WPF possède une propriété ShutdownMode qui est par défaut réglée sur OnLastWindowClose. En gros dès qu’il n’y a plus de fenêtres en vie, l’application va se fermer gentillement.

De ce fait, dans le cas du lancement de plusieurs fenêtre en série, dès que la première se ferme, l’application vérifie sa propriété ShutdownMode et se retrouve à se fermer puisque la fenêtre suivante n’a pas encore été instanciée! Ce qui fait que lorsque l’on va faire le Show() suivant, comme l’application est en cours de fermeture, la fenêtre va recevoir un Close et donc ne pourra pas s’ouvrir puisqu’elle a déjà été fermée :)

Deux solutions:

  • Instancier ses fenêtres toutes en simultanée avant de faire apparaitre la première
  • Mettre l’application sur le mode ShutdownMode.OnExplicitShutdown et s’abonner à l’événement Closed de la dernière fenêtre pour appeler la méthode Shutdown() sur l’application

 

Et le tour est joué…

Bookmark and Share

.Net, WPF

UrzaGatherer sur CodePlex

3. juin 2010

Ca y est ! C’est le début de la gloire.

UrzaGatherer est disponible sur CodePlex à cette adresse:

http://urzagatherer.codeplex.com/

 

N’hésitez pas à me faire des retours!

Bookmark and Share

UrzaGatherer

L’après BDC 2010

1. juin 2010

Bewise vient de mettre en ligne le site http://AfterBDC.bewise.fr

Vous y trouverez tout ce qui concerne les sessions et les photos de la Bewise Day Conference 2010.

Nous mettrons chaque semaine des nouveaux éléments.

Vous pouvez le suivre également sur Tweeter: http://twitter.com/AfterBDC

image

Bookmark and Share

Bewise

De l’utilisation intelligente d’Entity Framework 4.0

31. mai 2010

Un framework a beau être super puissant, il ne peut pas empêcher l'a mauvaise utilisation. Il peut tenter par de nombreux moyens de la réduire mais il ne peut l’empêcher.

Du moins pas sans se brider par la suite.

J’en veux pour preuve l’utilisation d’Entity Framework 4.0. Ce framework permet de manière extrêmement élégante de requêter une source de données. Et, bien utilisé, il permet aussi d’être très performant.

Voici un exemple issu d’UrzaGatherer: Mon modèle possède une collection de Card qui, entre autres, contient une propriété Check qui permet de définir si l’utilisateur détient complètement la carte en question. Dans le cadre de la treeview qui affiche les collections de cartes, je voulais modifier le texte de chaque collection en y ajoutant le nombre de cartes manquantes le cas échéant.

Pour se faire et comme tout est issu du binding dans UrzaGatherer, j’ai développé un ValueConverter utilisé ainsi:

<TextBlock Text="{Binding Converter={StaticResource CountConverter}, Mode=OneWay
, IsAsync=True}"
/>

Le code du converter était le suivant:

    public class CountConverter : IValueConverter
    {
    public object Convert(object value, Type targetType, object parameter, 
CultureInfo culture) { Expansion expansion = (Expansion) value; var query = from card in MainWindow.Entities.Cards where card.ExpansionID == expansion.ID select card; int check = 0; List<Card> cards = query.ToList(); int count = cards.Count; foreach (Card card in cards) { if (card.Check) check++; } int missing = count - check; if (missing == 0) return string.Format("- {0} cards", count); return string.Format("({0}/{1} - Missing : {2})", check, count, missing); } public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture) { return value; } }

Dans ce converter, on voit donc une requête LINQ sur les cartes en question, puis une transformation en liste pour faire notre comptage.

Et c’est là qu’apparait la mauvaise utilisation. En effet, la conversion en liste va effectivement faire la requête sur la base de données et créer les entités en mémoire. Ces entités qui peuvent être lourdes (c’est le cas ici ou chaque carte porte plusieurs images).

Tout ça pour juste obtenir un comptage.

Il faut garder à l’esprit que EF4 est efficace tant qu’on reste dans le monde des expressions LINQ, c’est à dire tant qu’on reste au final dans le monde SQL.

Ici par exemple, la solution pour être bien plus efficace est simple : Il ne faut pas utiliser de listes locales mais tout traiter en LINQ:

public object Convert(object value, Type targetType, object parameter, 
CultureInfo culture) { Expansion expansion = (Expansion) value; var query = from card in MainWindow.Entities.Cards where card.ExpansionID == expansion.ID select card; int check = query.Count(c => c.Check); int count = query.Count(); int missing = count - check; if (missing == 0) return string.Format("- {0} cards", count); return string.Format("({0}/{1} - Missing : {2})", check, count, missing); }

La différence est subtile mais ici tout se passera sur SQL Server. Aucune entité ne sera créée ni ramenée côté client. Les méthodes Count() issues de LINQ vont générer des requêtes efficaces côté serveur contrairement à la méthode ToList() qui va faire un bon gros SELECT des familles pour tout reconstruire en mémoire.

Donc en conclusion et en ce qui concerne Entity Framework 4.0 : Retardez toujours au plus tard la récupération des entités!!

Bookmark and Share

.Net, WPF ,