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

Bases de données Delphi Discussion :

[Tutoriel]Utiliser OLEDB en Delphi


Sujet :

Bases de données Delphi

  1. #1
    Expert éminent sénior

    Avatar de Nono40
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2002
    Messages
    8 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2002
    Messages : 8 640
    Points : 19 101
    Points
    19 101
    Par défaut [Tutoriel]Utiliser OLEDB en Delphi
    Bonjour à tous

    Franck Soriano nous propose un nouveau tutoriel qui vous fera découvrir l'utilistation d'OLEDB avec des applications Delphi

    Cet article présente comment utiliser directement OLEDB pour exécuter une requête sur une base de données. SQL Server est utilisé pour les exemples, mais ce tutoriel peut s'appliquer à n'importe quel SGBD.
    Grâce à OLEDB et la classe TMemoryDataSet présentée dans l'article précédent, on peut obtenir des performances quatre fois supérieures qu'avec une application ADO traditionnelle ou dbExpress.
    C'est article est le troisième de la série sur l'Optimisation des accès aux bases de données dont les deux premiers chapitres sont ici :
    I : Comparatif des API d'accès aux bases de données disponibles avec Delphi
    II : Développer un DataSet en mémoire
    Delphi :
    La F.A.Q. , 877 réponses à vos questions !
    264 sources à consulter/télécharger !

  2. #2
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    J'ai pris le soin de lire l'article en entier. Il est dans la tradition des autres articles, clair comme de l'eau de roche.

    Dois je comprendre que ADO.NET est le successeur de OLEDB sur .NET ?

  3. #3
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Merci.

    On peut voir les choses comme ça. Cependant, OLEDB est toujours utilisable à travers ADO.NET.

    ADO.NET est plus performant que OLEDB (en tout cas avec SQL Server) tout en restant très simple d'utilisation, avec un modèle de programmation semblable à ADO.

    En un mot, c'est la simplicité d'utilisation de ADO avec des performances encore meilleures que OLEDB.

  4. #4
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Avec du code managé, on arrive à de meilleures performances qu'avec du code natif .

    EDIT:

    J'ai fait une recherche rapide sur google et j'ai trouvé ce lien:

    http://www.google.fr/search?hl=fr&q=...vs+oledb&meta=

    Que faut-il comprendre ?

  5. #5
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Il ne faut pas croire que le code managé est plus lent que du Win32.

    D'abord, lorsque tu installe le framework .Net, la première chose que fait l'installer en fin d'install c'est lancer la compilation des images natives des assembly .Net.
    Donc au final, lorsque ton appli appelle ADO.NET, elle appelle du code natif, compilé spécifiquement pour ton architecture technique en utilisant toutes les optimisations possibles que tu n'aurais pas avec une compil générique pour tous les processeurs compatibles.

    Ensuite, les allocations mémoires avec le GC sont instantanées ce qui est loin d'être le cas avec la mémoire COM... Sans parler du fait que le traitement de collecte de la mémoire est déporté à un moment où la machine est moins chargée et exécuté dans un thread distinct, en tâche de fond.

    Ainsi, au final une appli .NET peut parfaitement être plus rapide qu'une appli Win32.

    Il y a quelques temps, j'avais fait un bench pour comparer les perfs en lecture d'ADO.NET et OleDb. Je précise encore une fois : avec SQL Server.

    De plus il ne faut pas perdre de vu que le provider ADO.NET pour SQL Server fait parti intégrante du Framework. Tu peux aussi passer par un provider OleDb, mais dans ce cas tu ajoutes une couche supplémentaire.
    Et bien sûr, la couche du dessus ne pourra pas être plus rapide que la couche du dessous sur laquelle elle s'appuie.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 735
    Points : 807
    Points
    807

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2006
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2006
    Messages : 41
    Points : 31
    Points
    31
    Par défaut
    Merci pour le tutorial

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2006
    Messages : 3
    Points : 4
    Points
    4
    Par défaut Profiter des performances en Delphi7
    Bonjour,

    Je me suis arrêté à Delphi7, mais j'aimerais évidemment pouvoir utiliser les résultats obtenus par Franck Soriano dans des applications basées sur SQL Server ou Access. Est-ce possible d'obtenir cela?
    Merci beaucoup.

    Josse Franken.

  9. #9
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    L'exemple de Franck Soriano est déjà valable pour SQL Server, ensuite pour les autres bases il suffit de récupérer le GUID de leur provider OLEDB respectif et de les utiliser en lieu et place de celui de SQL Server.

    Et la version de Delphi n'est pas très importante pour parvenir au même résultat (sauf s'il y a des boucles for...in mais qui peuvent être adaptées de toutes façons).
    La FAQ - les Tutoriels - Le guide du développeur Delphi devant un problème

    Pas de sollicitations techniques par MP -

  10. #10
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    J'ai écrit le code avec D2006 mais c'est du pareil au même avec D7.

    Il faudra peut-être faire quelques ajustement mineurs pour pouvoir compiler mon source avec D7 mais en soit, il ne devrait rien y avoir de bien bloquant (évidemment je n'ai pas testé). Il est même fort possible que le code compile directement en D7. Je ne me souviens pas avoir utilisé de nouveautés particulières du langage.

    Ensuite pour utiliser Access, il devrait suffir de choisir MS Jet 4 comme provider OLEDB, en passant par une chaîne de connexion, de la même façon que dans l'exemple pour ouvrir un fichier Excel...

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 2
    Points : 2
    Points
    2
    Par défaut P'tit complément
    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    {$APPTYPE CONSOLE}
     
    uses
      Windows,
      Classes,
      DB, ADODB, AdoInt, ActiveX, ComObj, OleDB,
      SysUtils;
     
    type TCGUID = class
        GUID: TGUID;
        constructor Create( Input: String);
      end;
     
    constructor TCGUID.Create(Input: String);
    begin
      GUID := StringToGUID( Input);
    end;
     
    function CreateADOObject(const ClassID: TGUID): IUnknown;
    var Status: HResult;
        FPUControlWord: Word;
    begin
      asm
        FNSTCW FPUControlWord
      end;
      Status := CoCreateInstance( ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Result);
      asm
        FNCLEX
        FLDCW FPUControlWord
      end;
      OleCheck(Status);
    end;
     
    procedure GetProviderNames(Names: TStrings);
    var
      RSCon: ADORecordsetConstruction;
      Rowset: IRowset;
      SourcesRowset: ISourcesRowset;
      SourcesRecordset: _Recordset;
      SourcesName, SourcesType, SourcesGUID: TField;
    begin
      SourcesRecordset := CreateADOObject(CLASS_Recordset) as _Recordset;
      RSCon := SourcesRecordset as ADORecordsetConstruction;
      SourcesRowset := CreateComObject(CLSID_OLEDB_ENUMERATOR) as ISourcesRowset;
      OleCheck(SourcesRowset.GetSourcesRowset(nil, IRowset, 0, nil, IUnknown(Rowset)));
      RSCon.Rowset := RowSet;
      with TADODataSet.Create(nil) do
      try
        Recordset := SourcesRecordset;
        First;
        SourcesName := FieldByName('SOURCES_NAME');      { do not localize }
        SourcesGUID := FieldByName('SOURCES_PARSENAME'); { do not localize }
        SourcesType := FieldByName('SOURCES_TYPE');      { do not localize }
        Names.BeginUpdate;
        try
          while not EOF do
          begin
            if SourcesType.AsInteger = DBSOURCETYPE_DATASOURCE then
              Names.AddObject( SourcesName.AsString, TCGUID.Create( SourcesGUID.AsString));
            Next;
          end;
        finally
          Names.EndUpdate;
        end;
      finally
        Free;
      end;
    end;
     
    const FranckSorianoExampleGUID : TGUID = '{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}';
     
    var SL: TStringList;
        Id: Integer;
     
    begin
      CoInitializeEx( nil, COINIT_MULTITHREADED);
      try
        SL := TStringList.Create;
        try
          try
            GetProviderNames( SL);
            for Id := 0 to SL.Count - 1 do
              if IsEqualGUID( TCGUID( SL.Objects[ Id]).GUID, FranckSorianoExampleGUID) then
              begin
                MessageBox( 0, 'Trouvé', 'OLEDBProvidersEnum', MB_OK);
                Break;
              end;
          finally
            while SL.Count > 0 do
            begin
                SL.Objects[ 0].Destroy();
                SL.Objects[ 0] := nil;
                SL.Delete( 0);
            end;
          end;    
        finally
          SL.Destroy;
        end;  
      finally
        CoUninitialize;
      end;
    end.

  12. #12
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 8
    Points : 10
    Points
    10
    Par défaut Utilisation de OLE DB avec les procédures stockées
    Bonjour,

    je souhaite exécuter des procédures stockées sous SQL Server 2005 à partir de Delphi 2009. J'ai utilisé le tutoriel de Franck, que je remercie au passage pour la qualité du tuto, et j'ai un petit souci. Je peux faire des requêtes basique sans problème, appeler des procédures stockées qui retourne un dataset sans problème, mais dès que j'appelle un procédure stockée avec des paramètres INPUT ou OUTPUT, au moment du cmd.Execute, j'ai un message me disant que le paramètre @toto n'est pas défini.
    J'ai donc cherché dans la doc de Microsoft et j'ai vu que pour les paramètres, il faut appeler SetParameterInfo en remplissant des structures. J'ai donc essayé cette méthode mais sans succès.
    Peut-on utiliser le code de Franck directement sans modification pour appeler des procédures stockées AVEC paramètres ? Si oui je serais ravi de connaître la marche à suivre :-)
    Sinon, avez vous un exemple de code avec le code de Franck qui me montrerait comment appeler une procédure stockée avec paramètres ?
    Merci à tous et bonne fin de journée.

  13. #13
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Je n'ai jamais chercher à exécuter de procédures stockées, par contre les requêtes paramétrées ne posent aucun problème.

    J'ai expliqué comment faire une requête paramétrée au II-E, et tu as un exemple d'utilisation au III-D.

    Le point important, c'est qu'il faut mettre un "?" dans la requête à la place du paramètre.

    Dès lors tu dois pouvoir exécuter une procédure stockée en jouant la requête :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    exec maprocedure ?, ?, ?

    Et si tu as un paramètre de sortie dans la SP :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    exec maprocedure ?, ?, ? output

    Par contre, de paramètres de type Date, il faut préciser la précision et le scale dans la définition du binding. Et j'ai un bug dans le passage des paramètres de type widestring. Il faut apporter quelques corrections à TOleDbParams.Create :

    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
     
    constructor TOleDbParams.Create(Params: TParams; ACmd : ICommand; Cnt : TOleDbConnection);
    ...
          ftDateTime:
            begin
              ParamSize := 8;
              CheckSize(Offset + 8 + ParamSize);
              DateValue := Param.AsDateTime;
              move(DateValue, PData^.Data[0], ParamSize);
              Binding.wType := DBTYPE_DATE;
              Binding.bPrecision := 23;
              Binding.bScale := 3;
            end;
          ftWideString, ftWideMemo:
            begin
              widestringValue := Param.AsWideString;
              ParamSize := length(widestringValue)*2;
              Binding.cbMaxLen := ParamSize;
     
              CheckSize(Offset + 8 + ParamSize);
     
              PData^.LengthValue := length(widestringValue)*2;
              move(widestringValue[1], PData^.Data[0], ParamSize);
     
              Binding.wType := DBTYPE_WSTR;
            end;

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 8
    Points : 10
    Points
    10
    Par défaut Petite avancée
    Bonjour Franck,
    merci pour ta rapidité de réponse.
    Alors j'ai repris ton code en mettant les ? avec les OUTPUT quand cela était nécessaire, et maintenant ça marche avec des paramètres INPUT, mais pas avec des paramètres OUTPUT.

    Pour que ce soit plus clair, voici mon bout de code que j'utilise :

    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
     
    procedure TSQLServerOLEDB.Test;
    var
      SQL : WideString;
      Params : TParams;
      Param : TParam;
      IDRet : integer;
    begin
      Params := TParams.Create;
      try
        //Creation des 2 parametres d'appel de la procedure stockee
        Param := Params.CreateParam(ftInteger, '@IDIn', ptInput);
        Param.Value := 6;
        Param := Params.CreateParam(ftInteger, '@IDRet', ptOutput);
        Param.Value := -1;
        //Appel de la procedure stockee
        SQL := 'EXEC psTEST ?, ? OUTPUT;';
        OleDbConnection.ExecSQL(SQL, Params);
        //Recuperation du parametre de retour
        IDRet := Params.ParamValues['@IDRet'];
        showmessage(IntToStr(IDRet));
      finally
        FreeAndNil(Params);
      end;
    end;
    et voici la procédure stockée de test que j'utilise (toute bête, elle me sert a vérifier le bon fonctionnement des paramètres INPUT et OUTPUT :

    Code sql : 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
     
    CREATE PROCEDURE psTEST
    	@IDIn int,
    	@IDRet int OUTPUT
    AS
    BEGIN
    	-- SET NOCOUNT ON added to prevent extra result sets from
    	-- interfering with SELECT statements.
    	SET NOCOUNT ON;
    	-- Verification des parametres
    	IF (@IDIn IS NULL) OR (@IDRet IS NULL)
    		RAISERROR('Paramètres non initialisés', 16, 1)
    	IF @@ERROR <> 0 RETURN
    	SET @IDRet = @IDIn
    	SET NOCOUNT OFF
    END

    Quand j'exécute cmd.Execute de TOleDbConnection.ExecSQL, j'ai une exception OLE DB remontée. "Paramètres non initialisés". En fait, au niveau de la procédure stockée, il semblerait que le @IDRet soit NULL.
    Pourtant, en faisant du pas à pas, les 2 paramètres sont bien initialisés correctement dans OleDbParams.Parameters.

    As-tu une petite solution pour ce problème ?
    Je te remercie et te souhaite une bonne journée
    David ;-)

  15. #15
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    C'est normal, tu as créé le paramètre de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Param := Params.CreateParam(ftInteger, '@IDRet', ptOutput);
    Param.Value := -1;
    Ton paramètre @IDRet est donc de type ptOutput. Etant en sortie seul, il n'est pas transmis par OLEDB lors de l'appel à SQL Server.
    Si tu veux transmettre une valeur au moment de l'appel et qu'elle soit modifiée en retour, il faut créer le paramètre en INPUT/OUTPUT, soit ptInputOutput.

    Déclarer un paramètre en sorti seul sert justement à optimiser le traffic réseau en évitant d'envoyer une valeur qui ne sert à rien.

    PS: Le ';' à la fin de la commande SQL ne doit pas servir à grand chose...

  16. #16
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 8
    Points : 10
    Points
    10
    Par défaut
    Ok, donc en mettant ptInputOutput, je n'ai plus ce problème de paramètre NULL.

    Par contre, ce que je souhaite, si tu regardes la procédure, c'est ne pas passer un paramètre qui ne sert à rien. @IDRet sert juste à récupérer la valeur de @IDIn, mais ne sert à rien dans l'exécution de la procédure, donc il doit bien être à ptOutput non ? Bon mais à la rigueur, ça ne me dérange pas de mettre les paramètres en InputOuput et de passer des valeurs inutiles.

    Sinon, si je mets ptInputOutput pour @IRDet, la valeur @IDRet dans le showmessage est toujours -1 au lieu de 6, comme si les paramètres n'avaient pas été mis à jour.

    On avance, on avance....:-)

    PS : oui le ; ne sert à rien mais j'aime bien le mettre ;-)
    PS2 : merci de m'aider à faire avancer le schmilblik !

  17. #17
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par wiccanhelios Voir le message
    Par contre, ce que je souhaite, si tu regardes la procédure, c'est ne pas passer un paramètre qui ne sert à rien. @IDRet sert juste à récupérer la valeur de @IDIn, mais ne sert à rien dans l'exécution de la procédure, donc il doit bien être à ptOutput non ? Bon mais à la rigueur, ça ne me dérange pas de mettre les paramètres en InputOuput et de passer des valeurs inutiles.
    Il faut savoir ce que tu veux. Si tu n'attends pas de valeur en entrée, il ne faut pas vérifier si le paramètre a une valeur dans ta procédure stockée !
    L'erreur "Paramètres non initialisés" c'est toi qui la déclenche dans ta SP lorsque le paramètre n'a pas de valeur en entrée...

    Donc met ton paramètre en ptOutput, et déclenche une erreur dans ta SP que si le paramètre @IDIn est à NULL.

    Sinon, si je mets ptInputOutput pour @IRDet, la valeur @IDRet dans le showmessage est toujours -1 au lieu de 6, comme si les paramètres n'avaient pas été mis à jour.
    Je vais faire le test.

  18. #18
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Bon, moi j'ai bien la bonne valeur.

    Regarde ce qui se passe en pas à pas. La valeur de retour du paramètre est reprise par TOleDbParams.UpdateParams.

  19. #19
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 8
    Points : 10
    Points
    10
    Par défaut
    bonjour Franck,
    désolé pour le retard mais je suis passé sur un autre projet.
    Sous delphi 2009, je n'ai toujours pas mon paramètre retour correcte. Je vais creuser un peu plus.
    Par contre, je me suis aperçu d'une chose : si je mets le code suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    //Creation des 2 parametres d'appel de la procedure stockee
        Param := Params.CreateParam(ftInteger, '@IDIn', ptInput);
        Param.Value := 6;
        Param := Params.CreateParam(ftInteger, '@IDRet', ptOutput);
    //    Param.Value := 0;
        //Appel de la procedure stockee
        SQL := 'EXEC psTEST ?, ? OUTPUT;';
        OleDbConnection.ExecSQL(SQL, Params);
        //Recuperation du parametre de retour
        IDRet := Params.ParamValues['@IDRet']
    en ne mettant pas de valeur par défaut pour le deuxième paramètre, dans ta fonction TOleDbParams.Create, tu mets PData^.NullStatus := DBSTATUS_S_ISNULL pour ce paramètre, ce qui génère ensuite une exception dans ma procédure stockée. (J'ai modifiée celle-ci, et je ne teste plus la valeur NULL sur le paramètre OUTPUT, mais ça déclenche quand même une exception). Est-ce normal car un paramètre output n'est fait que pour recevoir une valeur de retour. Je ne vois pas l'utilité de lui passer une valeur à l'appel de la procédure stockée alors que je n'utilise pas cette valeur dans la ps.

    Sinon pour mon soucis, je vais voir s'il n'y a pas un problème de calcul d'offset qui pourrait avoir lieu car je suis sous Delphi 2009 et certains types ont été changé. Je te tiens au courant.

  20. #20
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Dans les exemples de code que je donne, j'affecte une valeur au TParam même pour un paramètre en sortie seule, parce que c'est ce qui me permettais de typer le TParam.
    Dans ton cas, tu prends la peine d'indiquer un nom et un type au TParam lors de sa création. Donc tu n'as pas besoin de lui affecter de valeur.

    J'ai recompilé les sources qui sont en lignes et je me suis rendu compte que j'avais un bug que j'ai corrigé depuis, et que j'avais complètement oublié...

    Dans TOleDbParams.Create, on a le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        PData := @FData[0];
        Offset := 0;
        for i := 0 to Params.Count -1 do
        begin
          Param := Params[i];
          Binding := @Bindings[i];
     
          // Initialisation de l'index des paramètres.
          FParamInfo[i].Offset := Offset;
          FParamInfo[i].Size := Param.Size;
          ParamSize := 0;
    PData pointe sur la valeur du paramètre qui est fournie à OLEDB.
    Comme tu peux le voir, le pointeur est initialisé au début de la boucle pour pointer sur le début du buffer FData...
    Sauf que le pointeur n'est pas mis à jour lorsqu'on passe au paramètre suivant, ce qui a pour effet que seul le premier paramètre est transmis correctement à OLEDB...

    Il faut mettre à jour PData pour chaque paramètre, en le faisant pointé sur FData[Offset] :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
        for i := 0 to Params.Count -1 do
        begin
          PData := @FData[Offset];
          Param := Params[i];
          Binding := @Bindings[i];
     
          // Initialisation de l'index des paramètres.
          FParamInfo[i].Offset := Offset;
          FParamInfo[i].Size := Param.Size;
          ParamSize := 0;
    Evidemment, j'avais déjà la correction lorsque j'ai fait le test...
    Ca devrait corriger ton problème.

Discussions similaires

  1. [Tutoriel] Utilisation de Delphi Prism
    Par Nono40 dans le forum EDI
    Réponses: 0
    Dernier message: 19/05/2009, 16h38
  2. [adabas] Quel tutoriel utiliser ?
    Par fmdr dans le forum Autres SGBD
    Réponses: 1
    Dernier message: 26/12/2006, 11h08
  3. Comment utiliser Word avec Delphi 7 ?
    Par muquet dans le forum Débuter
    Réponses: 9
    Dernier message: 06/12/2005, 18h52

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