IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

[2005 / CLR TVF] yield return ?


Sujet :

Développement SQL Server

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 4
    Points : 4
    Points
    4
    Par défaut [2005 / CLR TVF] yield return ?
    Glop à vous.
    Ma première question concerne un petit problème que je rencontre au boulot.
    Sql Server 2005 permet de manipuler le xml, mais dans ce domaine, et bien disons que... en T-SQL, il n'est pas vraiment performant
    (ou alors je m'y suis vraiment pris comme un pied )

    J'ai donc besoin de créer un xml qui a globalement cette forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <liste AL1 = "" AL2="">
        <article A1 = "">
            <status>          <!-- balise non répétable et même potentiellement vide -->
                <s lib="" />
            </status>
            <meta desc="">
                <val key="" v=""/>
            </meta>
        </article>
    </liste>
    Générer ce xml depuis une requête T-SQL est coûteux, aussi, il avait été décidé de passer par le CLR pour le générer.
    On a rencontrer un problème (genre out of memory) avec l'implémentation en proc CLR (qui chargeait toutes les données et y allait à coups de DataTable.Select()), aussi j'ai essayé d'améliorer les choses en essayant de passer par une fonction table.
    J'ai réussi (le test de charge est pour demain), toutefois j'ai rencontré quelques difficultés (et c'était ma première tentative en CLR Sql Server).
    Tout d'abord, j'ai été ennuyé de ne pas pouvoir ouvrir plusieurs connections afin de lancer 2 ou 3 DataReader en parallèle (pour minimiser la consommation mémoire), mais bon, bon-gré mal-gré, j'ai contourné ça.
    En gros, voilà comment fonctionne mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    class myobj
    {
        clé;
        XmlDocument;
        myobj() {}
        myobj(k, x) {};
    }
    
    méthode static IEnumerable init(myparam):
    DataReader liste -> dataTable liste
    ArrayList res; // si je me souviens bien, ça doit être un type de ce genre
    foreach (DataRow in liste.Rows)
    {
        x = new XmlDocument
        construction nœud principal
        DataReader item --> nœud item
        DataReader dr_status
        if (dr_status.HasRows)
        {
            nœud status
            while (dr_status.Read())
              création nœud s
        }
        DataReader meta --> DataTable metas
        foreach (DataRow in metas.Rows)
        {
            nœud meta
            DataReader val --> nœud val
        }
    
        res.Add(new myobj(clé, x));
    }
    return res;
    
    methode FillRow(object source, les colonnes SqlTypées){ //peu importe non ? ;) }
    J'avais aperçu un ou deux codes où on ne faisait pas un return "bête et méchant" dans la méthode d'init, mais un yield return.
    J'ai donc essayé d'enlever les 2 lignes en orange ci-dessus en remplaçant l'ajout à l'ArrayList par un yield return new myobj(clé, x);
    Mon idée était d'essayer de linéariser la génération des données et leur "consommation" par le FillRow.
    Hélas, je me suis pris cette exception:
    System.InvalidOperationException: Data access is not allowed in this context. Either the context is a function or method not marked with DataAccessKind.Read or SystemDataAccessKind.Read, is a callback to obtain data from FillRow method of a Table Valued Function, or is a UDT validation method.
    Et là ... je comprends du coup pas.
    comment on doit faire pour pouvoir utiliser le yield ici ?
    ou alors quand peut-on l'utiliser dans une SqlFunction ?
    édit: voilà un lien msdn où j'avais vu ce fameux yield return ...page msdn

    Sinon, j'ai une deuxième question, très certainement liée à mon mauvais niveau d'anglais...
    J'ai lu quelques petites choses dessus, mais je n'ai pas compris l'utilité du SqlPipe
    Quel est l'exemple "ultime" qui permet de se rendre compte d'à quoi ça sert de manière qu'on hésite plus sur son rôle ?

  2. #2
    Membre confirmé Avatar de agemis31
    Profil pro
    DBA
    Inscrit en
    Octobre 2007
    Messages
    399
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DBA

    Informations forums :
    Inscription : Octobre 2007
    Messages : 399
    Points : 478
    Points
    478
    Par défaut
    Bonjour,

    Je trouve que SQL Serveur se débrouille plutôt pas mal avec le XML, surtout quand il est typé. Quelle est la technique utilisée pour la fabrication ? FOR XML (PATH) ?
    Je me permet de faire un peu de pub pour le livre de Jacob Sebastian 'the art of xsd'. C'est un excellent ebook qui propose une approche pratique des schémas xsd sous sql serveur, il est librement téléchargeable.


    @+

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 897
    Points : 53 135
    Points
    53 135
    Billets dans le blog
    6
    Par défaut
    Si vous voulez que la manipulation de données XML dans SQL soit performante, il faut faire deux choses :
    1) créer une collection de schéma XML et l'associer à votre colonne XML
    2) indexer votre XML selon le type de requête XQuery/XPath qui y sera majoritairement faites.

    Pour ma part j'ai obtenu des gains de perf de x 100 par rapport à un parser classique (genre Visual Studio) sur des masses de doc.

    A +

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 4
    Points : 4
    Points
    4
    Par défaut
    Merci de vos réponses;
    Je les ai lu ce matin mais ai préféré y réfléchir un minimum avant de répondre

    agemis31 :Lors de mon premier test avec génération complète du Xml par la requête, il s'agissait de for Xml Auto.
    Je suis loin d'être une bête en Xml, j'ai fait plusieurs essais avec mes notions et la doc.
    La structure des tables derrière et des jointures est un peu complexe, mais en gros, la requête générant le xml avait cette tête:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    Select
       key,
       ( Select
           ...,
          ( Select
             ...
            From status
            Where = T.key
            For xml auto, type
          ),
          ( Select
             ...
            From meta
              inner join val
            Where = T.key
            For xml auto, type
          ),
         From liste
           inner join article
         Where liste.key = T.key
         For xml auto, type
       )
    From T
    si j'ai bien tout compris au moment où je l'avais fait, j'avais été obligé d'imbriquer les requêtes For xml afin d'obtenir la bonne structure
    J'avais essayé de faire du for xml path sans parvenir à un résultat adéquat.
    Du coup de vos message, je vais essayer de générer côte-à-côte les 3 xml puis de les imbriquer dans un second temps.

    C'était en tout cas la génération de ce xml qui prenait trop de temps (genre plus de 2 minutes pour moins de 15000 lignes).

    SqlPro : je vais me pencher sur la question, je n'ai encore jamais essayé de faire du xsd et de l'index sur du xml en Sql server.
    Ça pourrait faire éviter de passer par le CLR et conserver suffisament de performances ?

    Sinon, à propos de yield return, il se pourrait que se soit parce qu'il faudrait que j'encapsule mon objet dans un second implémentant IEnumerable.
    (cf. http://msdn.microsoft.com/fr-fr/magazine/cc163473.aspx)

Discussions similaires

  1. Yield return dans un try; catch
    Par Seth77 dans le forum C#
    Réponses: 3
    Dernier message: 11/05/2012, 23h07
  2. [2005] CLR with execute as 'myUser'
    Par CUCARACHA dans le forum MS SQL Server
    Réponses: 0
    Dernier message: 23/06/2008, 09h55
  3. SQL SERVER 2005 CLR et owner ?
    Par zoltix dans le forum MS SQL Server
    Réponses: 0
    Dernier message: 20/08/2007, 10h58
  4. yield return et liste générique ?
    Par Thomas Lebrun dans le forum C#
    Réponses: 4
    Dernier message: 18/07/2007, 13h16
  5. "yield return" en VB
    Par Matthieu MEZIL dans le forum VB.NET
    Réponses: 3
    Dernier message: 06/02/2007, 13h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo