mardi 10 mai 2011

Optimisation des contrôles ASP.NET Ajax Control Toolkit

Ayant eu quelques problèmes de performance avec les contrôles Ajax Toolkit, je voudrais faire par de quelques informations pour optimiser leurs utilisations afin d'avoir un site web performant :).

Exemple de lourdeur si on ne fait rien : Mettre quatre control HTML Editor sur la même page et constater le temps de chargement de la page. Cela prend n fois plus de temps :(.

Sans blabla, voici la solution.

Deux étapes importantes :

  • dans le web.config il faut ajouter les lignes suivantes :
  
    
      
    
  
  • dans le master page ou une page web spécifique les lignes suivantes :
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
  
  
  


Il existe une troisième optimisation, mais elle nécessite de sniffer la liste des fichiers javascripts et de les déclarer dans le web.config de façon à ce qu'ils soit charger en fonction des besoins.
Je n'aime pas trop cette solution car elle impose 2 restrictions:

  1. La connaissance et la maintenance de cette liste
  2. Une limitation de 1024 caractères pour la liste.

Mais, il est facilement possible de faire autant de groupe que l'on veux pour inclure tout les fichiers (il y en a environ 45 pour le HTML Editor). Cela implique 4groupes avec 12 à 15 références chancun. Si on peut l'éviter, le mieux est de faire sans.

Pour info, la liste des fichiers javascript s'obtient avec le ScriptReferenceProfiler (pour télécharger la dll voir les liens au bas du post)

et la déclaration suivante dans la page web à sniffer :

<%@ Register Assembly="ScriptReferenceProfiler" Namespace="ScriptReferenceProfiler"    TagPrefix="microsoft" %> 
 

Ne pas oublier de mettre en référence la DLL dans le projet : ScriptReferenceProfiler.dll

Et en final, mettre la liste des fichiers dans le web.config avec les lignes suivantes :

    
       
          
             
             
             
          
       
    


et autant de ScriptManagerProxy qu'il faut :

  
     
        
           
            
        
     
  

Pour plus d'information, consulter les liens suivants :

http://lancezhang.wordpress.com/2008/11/15/aspnet-ajax-performance/
http://ajaxcontroltoolkit.codeplex.com/releases/view/65800
http://aspnet.codeplex.com/releases/view/13356

samedi 5 septembre 2009

Import/Export des schémas d’une BD SQL Server

Après plusieurs recherche chez Microsoft pour réaliser cette manipulation, je n’ai rien trouvé de vraiment concret, juste les liens suivant pour SQL 7 & 2000 et SQL 2005.

Ce que j’apprend c’est  qu’anciennement les diagrammes étaient sauvés dans la table dtproperties et maintenant sous SQL 2005 dans la table sysdiagrams.

En fait la meilleure solution que j’ai trouvé ce trouve sur le site de The Code Project. L’article est en anglais, mais je vais faire un tuto rapide, il n’y a rien de compliquer.

  1. Downloader le fichier Zip qui comporte 2 fichiers, à savoir :
    - Tool_ScriptDiagram2005.sql
    - Tool_VarbinaryToVarcharHex.sql

    Tool_ScriptDiagram2005.sql contient la procédure stocké qui vas extraire les informations de la table sysdiagrams et lui appliquer un template, afin de rendre autonome le code sql généré pour importer le schéma dans une autre bd ultérieurement.

    Tool_VarbinaryToVarcharHex.sql est une fonction qui est appelé par la procédure stocké.
    Elle transforme le binaire du schéma en une liste de valeur hexadecimal exploitatble dans un ficher sql.

  2. Ouvrir SQL Server et intégrer les 2 scripts sql dans la BD qui vous intéresse.

  3. Pour extraire un schéma. Demander une nouvelle requête afin de saisir et exécuter la commande suivante :
    exec Tool_ScriptDiagram2005 'LeNomDeMonSchema'
    Sauvegarder le résultat généré dans un fichier, par exemple monSchéma.sql.

  4. Pour importer un diagramme, rien de plus simple ouvrir le fichier sql du schéma généré et l'exécuter.
    La procédure stocké et la fonction "Tool_..." ne sont pas nécessaire. Le schéma sera recréé avec le même nom suivi de la date et l'heure d'import pour ne pas écraser le schéma existant.

Dans mon cas, je restaure souvent ma BD et je repars à vide donc je préfère que la date et l'heure ne soit pas présent derrière le nom du diagramme.
Pour cela j'ai modifié la procédure stocké existante "Tool_ScriptDiagram2005" en ajoutant les lignes de code suivantes:

  PRINT '    PRINT ''Removed uniqueness when diagram ' + @name + ' not exist'''
  SELECT @line =  
        '    IF not exists (SELECT [name] FROM sysdiagrams WHERE [name] = '''+ @name +''') '
  PRINT @line
  PRINT '        SET @DiagramSuffix = '''''

à insérer juste avant la ligne existante :

  PRINT '    PRINT ''Write diagram ' + @name + ' into new row (and get [diagram_id])'''

Tout ça, c'est bien, mais généralement on a plein de diagramme à gérer, donc le faire manuellement ce n'est pas le top. Il est possible d'utiliser des fichiers batch pour aller plus vite.

Pour extraire des schémas (Extract.bat):

@set SERVER=(local)
@set DB=NomDeMaDatabase

sqlcmd -d %DB% -E -S %SERVER% ^
 -Q "exec Tool_ScriptDiagram2005 'NomDeMonSchema'" ^
 -o NomDeMonSchema.sql

Pour Importer des schémas (Import.bat):

@set SERVER=(local)
@set DB=NomDeMaDatabase

:VERIF_ARGS
@REM Si arguments non vide on les prends en compte
@IF NOT "%~1"==""  @set SERVER=%~1
@IF NOT "%~2"==""  @set DB=%~2

:IMPORT
sqlcmd -d %DB% -E -S %SERVER% ^
 -i NomDeMonSchema1.sql ^
 -i NomDeMonSchema2.sql ^
 -i NomDeMonSchema3.sql ^
 -o OUTPUT_DIAGRAMS_IMPORT.log 

La section :VERIF_ARGS est utile si on a un autre batch qui l'appel. L'idée est d'être capable de l'appliquer pour différents environnement, comme Test ou Préproduction par exemple, par défaut tout est local.

L'option "-o OUTPUT_DIAGRAMS_IMPORT.log" permet d'avoir une log de l'exécution des imports afin de traquer les erreurs.

Voici un exemple du batch de restauration de ma bd en local qui appel l’import et met en place les 2 SQL pour gérer les diagrammes :

@echo on

@set SERVER=(local) 
@set DB=NomDeMaDatabase

:Restore DB - Version nnn
sqlcmd -d %DB% -E -S %SERVER%  -i Restore.sql -o OUTPUT_RESTORE.txt:CREATE DIAGRAMS
@echo.
@echo ** CREATE DIAGRAMS **
@cd Diagrams
@call import.bat %SERVER% %DB%
@echo.
@echo ** SQL TOOLS FOR DIAGRAMS **
sqlcmd -d %DB% -E -S %SERVER% -i "Tool_ScriptDiagram2005.sql"
sqlcmd -d %DB% -E -S %SERVER% -i "Tool_VarbinaryToVarcharHex.sql"
@cd ..

Tous mes scripts de schémas et tools sont mis dans un répertoire que j’ai nommé Diagrams.

Et un exemple du fichier Restore.sql pour avoir une solution complête :

DECLARE @TARGET_MDF VARCHAR(MAX)
DECLARE @TARGET_LDF VARCHAR(MAX)
DECLARE @SOURCE VARCHAR(MAX)

SET @SOURCE = 'C:\...\NomDuBackupDeMaBD.BAK' 
SET @TARGET_MDF = 'C:\...\MSSQL\Data\NomDeMaBD.mdf'
SET @TARGET_LDF = 'C:\...\MSSQL\Data\NomDeMaBD_Log.ldf'

USE master

PRINT '-- Drop DB --'

IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'NomDeMaBD')
    ALTER DATABASE [NomDeMaBD] SET SINGLE_USER WITH ROLLBACK IMMEDIATE

IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'NomDeMaBD')
    DROP DATABASE [NomDeMaBD]


PRINT '-- Restore DB --'

RESTORE DATABASE [NomDeMaBD]
FROM DISK = @SOURCE
WITH 
MOVE 'NomDeMaBD' TO @TARGET_MDF,
MOVE 'NomDeMaBD_log' TO @TARGET_LDF

Voilà, bon usage.

Pour avoir une BD de démo, au besoin, je vous propose de prendre AdvenureWorks ici.

mercredi 26 août 2009

Comment garder l’ancienne version de Live ou MSN Messenger ?

J’adore ce que fait Microsoft en général mais là je trouve qu’il y a de l’abus et ce n’est pas la première fois concernant MSN Messenger. Je craque.

La nouvelle version de MSN Messenger, nommé Live Messenger nous force à installer plein de chose sur sont poste sans qu’on les ai demandées. Ex : Je lance l’installation de Live Messenger, le setup est tout petit mais ce n’est qu’un prélude à tous les outils Live Microsoft … On décoche tous les produits en ne gardant que Live Messenger et là 70 meg à installer, il pèse lourd le bébé, on est loin des 15meg d’il y a 1 ou 2 ans. Ils travaillent fort les gars de Microsoft.

Ok, Ok, d’ac, je lance l’installation, et je regarde la barre d’avancement, et là, je vois quoi RepportError qui s’installe, j’ai jamais demandé ça moi. GGRRrrrrrr……

Ou dans le style, vous avez l’ancienne version de Live Messenger ou MSN Messenger qui répond complètement à vos besoins, vous lancez l’appli et là un super message vous dit qu’il existe une nouvelle version, vous répondez non, pas de message et pas de connexion, on recommence, et bah! zut! même chose plus possible de se connecter, cela ne marche plus, on refais qqes essai, même chose. Ils font quoi chez Bilou,  GGRRrrrrrr……

Là, sérieux, j’aime vraiment pas ces manière de faire. Par contre c'est une bonne manière pour perdre de la clientèle. Je serais eux, je ne pousserais pas trop loin le bouchon.

Ok, on se calme. Donc comment faire pour garder son ancienne version de Live ou MSN Messenger, voici la procédure :

  • Fermer votre Live ou MSN Messenger.
  • Aller dans le répertoire C:\Program Files\MSN Messenger.
  • Retrouver le fichier msnmsgr.exe.
  • Demander les Propriétés et allez dans l’onglet Compatibilité.
  • Changer le mode de compatibilité pour Windows 2000 et cliquer OK.
  • Redémarrer Live ou MSN Messenger, le programme de réparation de l’application peut démarrer, laisser le faire.
  • Redémarrer Live ou MSN Messenger une dernière fois, ca y est tout est ok maintenant.

Ça fait du bien de s’exprimer des fois :)

MAJ : 2009/09/16 Il semblerait que Microsoft force les gens à passer sous la dernière version de MSN Messenger, en bloquant définitivement avec le même message, l’utilisation des anciennes version. Encore là, l’astuce est de prendre le mode de compatibilité Windows 2000 et de fermer puis relancer votre MSN Messenger. C’est le seul qui reste opérationnel, malheureusement.

vendredi 14 août 2009

L’instruction yield pour récupérer la sélection d’éléments d’une liste

L'idée n'est pas de faire un cours sur l'instruction yield, pour cela voir les liens suivants :

http://msdn.microsoft.com/fr-fr/library/9k7k7cf0.aspx

http://romainverdier.developpez.com/articles/dotnet/le-mot-cle-yield-et-les-iterateurs-en-csharp/

Mais de donner un petit plus quand on code avec des listes et très souvent on refait la même chose à savoir récupérer la sélection d'une liste pour lui appliquer un traitement particulier.

Donc le but du jeu est ; Comment peut-on faire pour éviter la duplication des Foreach ou While ou autre afin de récupérer une sélection d’éléments ?
Pour être le plus souple possible, je propose d’utiliser une méthode, nommé Cast, qui soit le plus générique possible.

        // Méthode qui permet d'extraire les objets d'une collection.
        // Valable à partir de Framework .NET 2.0
        // On peut mettre cette méthode dans une classe d’aide(Helper)
        // de facon à l'appeler ailleur pour tout objet qui contient
        // une collection IEnumerable (listBox,)
        IEnumerable<T> Cast<T>(IEnumerable items)
        {
            foreach (object item in items)
                yield return (T)item;
        }

Dans l’exemple suivant, j’utilise une class nommé Personne comme type avec deux propriétés, à savoir : Nom et Prenom. L’utilisation d’un objet string ou autre est possible aussi (voir l’exemple dans le code complet).
Voila le code dans sa totalité.

Merci Éric pour tes idées :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Collections;
using System.Windows.Forms;

namespace Yield_SelectedItems
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();

            List<Personne> personnes = new List<Personne>();
            personnes.Add(new Personne("Hugo", "Victor"));
            personnes.Add(new Personne("Zola", "Emile"));
            personnes.Add(new Personne("Dupont", "Thomas"));
            personnes.Add(new Personne("Dupond", "Daniel"));
            personnes.Add(new Personne("Super Dupond", "Daniel"));

            listBox1.Items.Clear();
            listBox1.Items.AddRange(personnes.ToArray());

        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Récupérer que les objets sélectionnés
            List<Personne> maSelections = new List<Personne>(Cast<Personne>(listBox1.SelectedItems));

            // On créer un objet list de type (chaine de caractère) pour générer
            // avec la méthode Join un saut de ligne facilement, sans avoir à 
            // gérer le premier ou le dernier retour chariot de trop.
            List<string> s = new List<string>();
            foreach (Personne onePersonne in maSelections)
            {
                s.Add(string.Format("{0} {1}", onePersonne.Prenom, onePersonne.Nom));
            }
            String nomPrenom = string.Join("\r", s.ToArray());

            // On affiche le résultat.
            System.Windows.Forms.MessageBox.Show(nomPrenom);


            // Démo avec une list de string
            ListBox mesProduits = new ListBox();
            mesProduits.SelectionMode = SelectionMode.MultiExtended;
            mesProduits.Items.Clear();

            // J'alimente ma listbox
            List<string> listProduits = new List<string>();
            listProduits.Add("Produit A");
            listProduits.Add("Produit B");
            listProduits.Add("Produit C");
            listProduits.Add("Produit D");
            listProduits.Add("Produit E");
            mesProduits.Items.Clear();
            mesProduits.Items.AddRange(listProduits.ToArray());

            // Je sinule une sélection
            mesProduits.SelectedItems.Add(listProduits[0]);
            mesProduits.SelectedItems.Add(listProduits[3]);

            // On récupère les produits sélectionnés
            List<string> monChoix = new List<string>(Cast<string>(mesProduits.SelectedItems));

            // On les affiches.
            System.Windows.Forms.MessageBox.Show(string.Join("\r", monChoix.ToArray()));


            // Lol, plus simple. Comme quoi des fois...
            Personne[] essai2 = new Personne[listBox1.SelectedItems.Count * 2]; // Je double la taille pour tester le mode Append
            listBox1.SelectedItems.CopyTo(essai2, 0);
            listBox1.SelectedItems.CopyTo(essai2, 3); // Append mode
            List<string> s2 = new List<string>();
            foreach (Personne onePersonne in essai2)
            {
                s2.Add(string.Format("{0} {1}", onePersonne.Prenom, onePersonne.Nom));
            }
            // On les affiches.
            System.Windows.Forms.MessageBox.Show(string.Join("\r", s2.ToArray()));


            // Lol, plus simple. Comme quoi des fois...
            string[] essai3 = new string[mesProduits.SelectedItems.Count];
            mesProduits.SelectedItems.CopyTo(essai3, 0);
            List<string> soluce3 = new List<string>(essai3);
            // On les affiches.
            System.Windows.Forms.MessageBox.Show(string.Join("\r", soluce3.ToArray()));

        }


        // Méthode qui permet d'extraire les objets d'une collection.
        // Valable à partir de Framework .NET 2.0
        // On peut mettre cette méthode dans une classe d’aide(Helper)
        // de facon à l'appeler ailleur pour tout objet qui contient
        // une collection IEnumerable (listBox,)
        IEnumerable<T> Cast<T>(IEnumerable items)
        {
            foreach (object item in items)
                yield return (T)item;
        }

    }


    class Personne
    {
        private string _nom;
        private string _prenom;

        public Personne()
        {
        }

        public Personne(string nom, string prenom)
        {
            Nom = nom;
            Prenom = prenom;
        }

        public string Nom
        {
            get { return _nom; }
            set { _nom = value; }
        }

        public string Prenom
        {
            get { return _prenom; }
            set { _prenom = value; }
        }

        // l'override de la méthode string est utilisé pour populer le listbox.
        public override string ToString()
        {
            return string.Format("{0} {1}", Nom, Prenom);
        }
    }

}

mardi 28 juillet 2009

Comment copier les colonnes d’entête de la grille de résultat d’une requête SQL ?

Voici une petite astuce bien pratique pour récupérer, lors d’un couper/coller, les colonnes de l’entête quand on est en mode grille dans Microsoft SQL Server Management 2005 :

Allez dans Outils/Options../Résultat des requêtes/SQL Serveur/Mode texte

et cocher l’option  Inclure l’entête de colonne dans la copie de la grille résultat.

Attention : Il faut malheureusement fermer complètement SQL Server Manager et le ré-ouvrir. N’oublier pas de sauvegarder votre requête avant.

jeudi 23 juillet 2009

RTM Windows 7 is available

C’est fait, Microsoft c’est décidé, la version officiel de Windows 7 est disponible.

Pour plus d’information, voir le post (en anglais) de cette annonce sur le blog de Microsoft ici.

Il semblerait que pour les gens qui possèdent un compte MSDN, la version téléchargeable ne soit pas disponible avant le 6 aout en version anglaise:(.

Cette version date du 13 juillet compilé à 12h55 et a comme numéro de build : 7600.16385.090713-1255

Vivement la version Française.

vendredi 17 juillet 2009

Publier du code avec SyntaxHighlighter sur Blogger


L’installation se fait en 4 étapes :

  1. On télécharge la version que l’on veut ici (v1.5.1) ou ici (v2.0.nnn)
  2. On extrait le contenu pour héberger les fichiers sur un site ou en utilisant l’un des liens suivant :
  3. On se connecte sur son bloque et l’on vas dans (Tableau de bord / Mise en page / Modifier le code HTML) pour modifier le modèle du blogue en ajoutant quelques lignes en fonction de la version. On ne se casse pas la tête, il faut aller à la fin du modèle et juste après la ligne suivante “<!-- end outer-wrapper -- >” on insère le code suivant :
  • Version 1.5.1
<link href='http://alexgorbatchev.com/pub/sh/1.5.1/styles/SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>

<script language='javascript' src='http://alexgorbatchev.com/pub/sh/1.5.1/scripts/shCore.js'/>
<script language='javascript' src='http://alexgorbatchev.com/pub/sh/1.5.1/scripts/shBrushJScript.js'/>
<script language='javascript' src='http://alexgorbatchev.com/pub/sh/1.5.1/scripts/shBrushCSharp.js'/>

<script language='javascript'>
dp.SyntaxHighlighter.BloggerMode();
dp.SyntaxHighlighter.HighlightAll('code');
</script>
  • Version 2.0.nnn
<link href='http://alexgorbatchev.com/pub/sh/2.0.320/styles/shCore.css' rel='stylesheet' type='text/css'/> 
<link href='http://alexgorbatchev.com/pub/sh/2.0.320/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>

<script src='http://alexgorbatchev.com/pub/sh/2.0.320/scripts/shCore.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/2.0.320/scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/2.0.320/scripts/shBrushJScript.js' type='text/javascript'></script>

<script type='text/javascript'>
SyntaxHighlighter.config.bloggerMode = true
SyntaxHighlighter.all();
</script>

Après plusieurs heures de recherche et d’essai (merci au post de Burca Victor Ciprian). Le truc, pour faire fonctionner SyntaxHighlighter correctement avec Blogger, c’est la ligne suivante qui doit être ajouter dans modèle du blogue (Ligne déjà présente dans les scripts précédents) :

  • Pour la version 1.5.1 :  dp.SyntaxHighlighter.BloggerMode();
  • Pour la version 2.0.nnn :   SyntaxHighlighter.config.bloggerMode = true

Les gens qui ne sont pas avec Blogger, doivent retirer cette ligne.

Si on ne met pas ces lignes, on obtient le cas suivant avec un code incompréhensible et plein de balise <BR />. Exemple :

  4.  Dernière phase, il ne reste plus qu’à formater le code que l’on veux publier avec les balises suivantes :

  • Pour la v1.5.1 :
    <pre name="code" class="[non du langage]">
    [ici votre code]
    </pre>
  • Pour la v2.0.nnn :
    <pre class="brush: [nom du langage];"
    [ici votre code]
    </pre>
Il faut remplacer [nom du langage] par le nom du langage (exemple : CSharp, js, etc…) et [ici votre code] par le morceau de code que vous voulez présenter. N’oublier pas d’ajouter le lien du langage que vous voulez afficher dans le modèle de votre blogue.

Voila, bon blogue à vous :).

Membres