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

Langage Delphi Discussion :

DCOM et TClientDataset dans application cliente


Sujet :

Langage Delphi

  1. #1
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut DCOM et TClientDataset dans application cliente
    Bonjour à tout(e)s

    Je viens de porter le code d'une application Delphi 6 vers XE 10.
    Il s'agit en fait de 2 applications, un serveur DCOM et une application cliente.

    Le code "ancien" utilise parfois un TClientDataset pour récupérer des données du serveur.

    Côté serveur :
    • un objet qui hérite de TCustomProvider
    • une procédure qui définit le dataset lié au provider .


    Côté client
    • création d'une instance Cds de TClientDataset
    • appel à la procédure distante qui fait (ou confirme) le dataset à utiliser
    • renseigne les propriétés RemoteServer et ProviderName
    • Ouverture de Cds


    Et là, gros crash ... Message : "Catastrophic failure"

    à force de fouiller, je vois qu'il n'y a aucune information de structure de de champs dans Cds. (fournisseur de données manquant)

    Problème, le code qui régit ce processus n'a pas changé.
    Ce qui veut dire que ça fonctionnait dans l'ancienne version de Delphi.

    Question : Est-ce que quelqu'un ici aurait connaissance de modification de comportement du TClientDataset entre ancienne et nouvelle version de Delphi ?

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 043
    Points : 40 957
    Points
    40 957
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    j'ai déjà eu quelques problèmes avec de vieux fichiers .cds, donc déjà avec une application totalement indépendante est-il possible d'ouvrir les fichiers cds ?
    est-ce que les descriptions de colonnes sont incluses dans le cds ?
    Je ne sais plus comment je m'étais dépatouillé de ce truc désolé
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut
    Ah ! Je m'aperçois que je me suis mal exprimé.
    Le Cds t'a induit en erreur. C'est le nom du composant TClientDataset.
    Je vais reprendre l'enchainement des actions.

    Client:
    crée un objet TClientDataset.
    appelle une fonction PrepareDataset du server

    Server: (les données sont dans une base Interbase)
    PrepareDataset :
    Assigne le TSQLQuery à la TSQLConnection lié à la base de données
    met à jour un TSQLQuery en lui assignant le SQL correspondant à la demande du client (en fonction d'un code numérique)
    renseigne éventuellement les paramètres de la requête avec les valeurs reçues en paramètres

    Client:
    Assigne au clientdataset la propriété remoteserver correspondante au server COM
    Assigne le providername correspondant au provider lié à la requête sur le server.
    Ouvre le client dataset

    Et c'est là que ça craque. Fournisseur ou paquet de données manquants.
    C'est le problème que l'on règle quand on a sur la même form un clientdataset lié à un dataset et qu'on essayer de l'ouvrir sans avoir utiliser le menu contextuel pour récupérer la structure du dataset dans le clientdataset.


    Et tout ça fonctionnait avec la version précédente de Delphi.
    J'ai beau chercher, je n'ai rien changé de critique dans le code entre les 2 versions (à part la version Interbase qui passe de IB6 à IB2017).

    Le pire, c'est que si le TSQLQuery et son provider existe et sont déjà paramétrés (en terme de structure de champs) sur le server, ça fonctionne.

    C'est un peu comme si définir le SQL du TSQLQuery au runtime empêchait la récupération des données côté client.

    Je posais la question d'un changement éventuel entre les versions de Delphi parce que ça fait plusieurs jours que je galère sur ce truc.
    Là, j'en suis au stade où je vais recoder ce système pour éviter le SQL créé dynamiquement mais ça va me prendre beaucoup de temps. :-(

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 043
    Points : 40 957
    Points
    40 957
    Billets dans le blog
    62
    Par défaut
    Bonjour
    Citation Envoyé par Papy214 Voir le message
    Le Cds t'a induit en erreur.
    complètement enduit même
    C'est un peu comme si définir le SQL du TSQLQuery au runtime empêchait la récupération des données côté client.
    Est-ce qu'un prepare pourrait jouer ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  5. #5
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut
    J'ai essayé le prepare, sans succès.

    L'ouverture du TSQLQuery suivi d'un close pour être sûr que tout soit bien initialisé côté serveur ne change rien non plus.

    J'utilise la JCL pour avoir une trace complète de l'erreur et on y voit bien le setactive du clientdataset qui arrive sur un DoGetRecords qui plante comme un sauvage.
    Normal puisqu'il n'y a aucune notion de la structure des données à récupérer :-(

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Je connecte des TClientDataSet à la volée à des TOraQuery crée à la volée sans aucun soucis en RunTime
    Je n'utilise jamais les champs persistants du TOraQuery (le SQL est généré via RTTI dans une couche ORM maison)
    Idem, Prepare, Bind puis Open

    Par contre, cela fait belle lurette que DCOM est abandonné !
    Remplace le par un Web Broker DataSnap (TWebConnection), cela simplifie grandement le déploiment (Plus l'usinagaz des droits Windows, simplification sur l'utilisation de port, juste HTTP ou SSL, ton admin réseau peut s'amuser avec son proxy, firewall ...)
    C'est vraiment le moment surtout avec un tel saut de version

    D'ailleurs, je vais surement utiliser cette technique pour certaine récupération de données Versus un Server REST, voir ce qui fonctionne le mieux (débit sur bcp de requête à petit volume versus peu de requête à gros volume)

    Le 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
    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
    //------------------------------------------------------------------------------
    (*                SoLuTions is an Versatile Library for Delphi                 -
     *                                                                             -
     *  Copyright "SLT Solutions", (©2006)                                         -
     *  contributeur : ShaiLeTroll (2012) - Création du TSLTClientDataSetAssistant en C++Builder 2007
     *  contributeur : ShaiLeTroll (2015) - Traduction du TSLTClientDataSetAssistant en Delphi XE2
     *                                                                             -
     *                                                                             -
     * Ce logiciel est un programme informatique servant à aider les développeurs  -
     * Delphi avec une bibliothèque polyvalente, adaptable et fragmentable.        -
     *                                                                             -
     * Ce logiciel est régi par la licence CeCILL-C soumise au droit français et   -
     * respectant les principes de diffusion des logiciels libres. Vous pouvez     -
     * utiliser, modifier et/ou redistribuer ce programme sous les conditions      -
     * de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA    -
     * sur le site "http://www.cecill.info".                                       -
     *                                                                             -
     * En contrepartie de l'accessibilité au code source et des droits de copie,   -
     * de modification et de redistribution accordés par cette licence, il n'est   -
     * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,   -
     * seule une responsabilité restreinte pèse sur l'auteur du programme,  le     -
     * titulaire des droits patrimoniaux et les concédants successifs.             -
     *                                                                             -
     * A cet égard  l'attention de l'utilisateur est attirée sur les risques       -
     * associés au chargement,  à l'utilisation,  à la modification et/ou au       -
     * développement et à la reproduction du logiciel par l'utilisateur étant      -
     * donné sa spécificité de logiciel libre, qui peut le rendre complexe à       -
     * manipuler et qui le réserve donc à des développeurs et des professionnels   -
     * avertis possédant  des  connaissances  informatiques approfondies.  Les     -
     * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du      -
     * logiciel à leurs besoins dans des conditions permettant d'assurer la        -
     * sécurité de leurs systèmes et ou de leurs données et, plus généralement,    -
     * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.          -
     *                                                                             -
     * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez      -
     * pris connaissance de la licence CeCILL-C, et que vous en avez accepté les   -
     * termes.                                                                     -
     *                                                                             -
     *----------------------------------------------------------------------------*)
    unit SLT.DB.DBClient;
     
    interface
     
    uses Data.DB, Datasnap.DBClient, MidasLib, Datasnap.Provider;
     
    type
      /// <summary>Boite à outil pour la classe TClientDataSet</summary>
      /// <remarks>Le TSLTClientDataSetAssistant n'est pas un class helper car cela n'était pas possible sous C++Builder 2007</remarks>
      TSLTClientDataSetAssistant = class(TObject)
        class function CloneDataSet(ADataSet: TDataSet): TDataSet;
        class function IsRecordCountable(ADataSet: TDataSet): Boolean;
      end;
     
    implementation
     
    //------------------------------------------------------------------------------
    class function TSLTClientDataSetAssistant.CloneDataSet(ADataSet: TDataSet): TDataSet;
    var
      ClientDS: TClientDataSet absolute Result;
      ProviderDS: TDataSetProvider;
    begin
      ClientDS := TClientDataSet.Create(nil);
     
      ProviderDS := TDataSetProvider.Create(nil);
      try
        // Je préfère SetProvider par rapport à ProviderName et sa bidouille avec le Owner !
        ClientDS.SetProvider(ProviderDS);
        try
          ClientDS.PacketRecords := -1; // garanti la copie des données !
          ProviderDS.DataSet := ADataSet;
          ClientDS.Open(); // Copie les Données d'un seul coup !
     
          // Par Défaut LogChanges est à true, ainsi les modifications restent en mémoire et cela ne tente pas d'altérer un DataSet qui encore lié malencontreusement sans un appel explicite à ApplyUpdates
          // Attribuez la valeur false à LogChanges si vous n'avez pas l'intention de mettre à jour la base de données avec les modifications de l'ensemble de données client
          // Avec le finally, il n'y a pas de risque d'un lien malencontreux
          ClientDS.LogChanges := False;
        finally
          ClientDS.SetProvider(nil); // on détache, on ne conserve que la copie en mémoire
        end;
      finally
        ProviderDS.Free();
      end;
    end;
     
    //------------------------------------------------------------------------------
    class function TSLTClientDataSetAssistant.IsRecordCountable(ADataSet: TDataSet): Boolean;
    begin
      Result := (ADataSet is TClientDataSet) and (TClientDataSet(ADataSet).PacketRecords = -1);
    end;
     
     
     
    end.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut
    Alors je ne comprends pas pourquoi ça ne fonctionne pas ici. :-(
    Je l'ai tourné dans tous les sens sans arriver à quelque chose de fonctionnel.
    Je vais y repasser encore une heure ou deux et après, je repasse tout en statique.

    Pour ce qui est d'abandonner DCOM, je suis bien d'accord avec toi mais le problème est qu'il s'agit d'un ensemble de plusieurs projets clients avec un même serveur.
    Et le client n'a pas du tout prévu le budget pour changer la techno utilisée.
    Il s'agit à la base d'une simple migration vers Delphi XE10.
    Sinon, j'aurais tout viré avec plaisir. Comme souvent, question de gros sous :-)

    Je vais tout de même jeter un coup d'oeil à ton code pour voir si j'ai zappé un truc.

    Merci

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Tu peux aussi migrer en douceur le DCOM vers DataSnap
    C'est ce que j'ai pu voir dans une ancienne boite (Editeur alors le budget n'est pas le même, surtout si c'est un gain en intervention sur de nombreux sites)

    DCOM
    c'est Out-Of-Process
    Client COM <-> DCOM <-> Serveur COM

    Le Serveur DCOM est instancié automatiquement si j'ai bon souvenir
    Il n'y a pas d'installation du COM sur le Poste Client


    COM + DataSnap
    c'est In-Process
    Client COM <-> Client BridgeCOM DataSnap <-> DataSnap <-> Serveur BridgeCOM DataSnap <-> Serveur COM


    Le Serveur BridgeCOM DataSnap doit être lancé comme un Service
    Le Serveur COM est instancié par le Bridge
    Le Client est installé sur le Client mais c'est via un switch, soit cela tourne en local, soit cela ne fait qu'invoquer le Client BridgeCOM DataSnap



    Qu'est-ce que ce Bridge?
    C'est juste une couche qui sérialise les propriétés et valeurs en JSON, cela les envoie en REST, et cela réceptionne fait appel au COM au bout

    Dans ton code, tu ne changes rien, c'est toujours du COM
    Dans tes serveurs, plus de DCOM mais du DataSnap et des COM installés localement sur les postes et sur le serveur
    On avait un petit flag pour dire si l'on était en COM Local ou en COM via DataSnap
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Membre émérite

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 388
    Points : 2 999
    Points
    2 999
    Par défaut
    J'ai vu le commercial de la boite qui va proposer le changement de techno au client. On verra bien sa réaction.

    Merci de tes conseils toujours avisés.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Authentification Windows dans application Client/Serveur
    Par dfgs83 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 31/07/2010, 02h54
  2. Verrouillage d’enregistrement dans une application Client/server
    Par touhami dans le forum Connexion aux bases de données
    Réponses: 13
    Dernier message: 07/07/2008, 22h05
  3. Intéger un OCX dans une application Client léger
    Par BB85_TIGRIS dans le forum Documents
    Réponses: 1
    Dernier message: 07/09/2007, 11h00
  4. Réponses: 1
    Dernier message: 10/09/2006, 13h02
  5. [OC4J 9.0.2] plusieurs modules clients dans application.xml
    Par Mokhtar BEN MESSAOUD dans le forum Autres
    Réponses: 2
    Dernier message: 11/02/2005, 10h18

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