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 :

Comment utiliser les composants de données et faire de la programmation orientée objet


Sujet :

Bases de données Delphi

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 229
    Points : 60
    Points
    60
    Par défaut Comment utiliser les composants de données et faire de la programmation orientée objet
    Bonjour messieurs,

    Je développe une application delphi7 qui utilise une base de données Ms Sql Server 2005. Je fais de la programmation orientée Objet. Je crée mes objets métiers que je renseigne puis j'enregistre par des méthodes Store(), Update() et Delete() qui font appel à des procédures stockées dans la base de données.
    Exemple de manipulation d'objet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     Obj_Client:=TClient.create();
     Obj_Client.nom:=dbedit_Nom.text;
     Obj_Client.prenom:=dbedit_Prenom.text;
     Obj_Client.store();// enregistre le client dans la base
    Voici comment je procède pour manipuler mes données de la base.
    Maintenant je souhaite utiliser des composants de données liés à une source de données (MyDataSource) et lier un composant DBNavigator pour naviguer entre mes données.

    Mon problème est que quand je dois faire une insertion,modification je ne peux pas utiliser mes Objets métier directement car mes composants de données sont liés au DataSource. Je suis donc obligé d'ouvrir ma table en faisant MyDataSet.insert ou MyDataSet.Edit. Ce qui me permet de saisir dans mes champs de données, puis je dois faire un post
    pour enregistrer les données dans la table.

    Moi je souhaiterais ne pas faire de Mydataset.insert ou Mydataset.edit ou encore Mydataset.post mais plutôt :
    Obj_Client:=TClient.create();
    Obj_Client.nom:=dbedit_Nom.text;
    Obj_Client.prenom:=dbedit_Prenom.text;
    Obj_Client.store();// enregistre le client dans la base
    Voici un peu ce que je souhaite faire: charger mes enregistrements dans une dbgrid,dbedit, naviger entre les données, saisir de nouveaux objets, modifier et enfin les mettre à jour en utilisant mes méthodes Obj_Client.store(),Obj_Client.Update() et Obj_Client.Delete().
    Je souhaite naviguer entre les données(premier,précedent,suivant,dernier).


    Je souhaiterais que que vous m'aidiez à trouver un bonne solution.
    Es-ce que je dois utiliser les composants de données ou utiliser de simple composants?
    Comment dois-je procéder?
    Merci pour votre compréhension.

  2. #2
    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
    Ah c'est bien le problème !
    Avec XE2, les LiveBindings pourraient une nouveauté intéressante à exploiter !
    Sinon avec Delphi 7, tu n'aurais pas une version entreprise, cela inclu BOLD !
    Regarde InstantObjects, cela fait déjà tout !

    Enfin, tu peux donc écrire ta propre couche d'objet persistant !
    Tes objets peuvent très bien utilisé un TDataSet interne !
    L'objet fourni une propriété DataSource, cela permet de lier un objet le TDataSet interne avec les DBControls !

    Ton code serait donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     Obj_Client:=TClient.create();
     Obj_Client.DataSource := Form1.DataSource1;
     Obj_Client.LoadByID(1); // Génère le SQL et l'execute
     Obj_Client.Edit();
    Dans le bouton valider
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Obj_Client.store();// enregistre le client dans la base
    Store utilise le Post du DataSet interne, ou alors, tu peux générer ton propre SQL à la volée

    je te DECONSEILLE vivement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     Obj_Client.nom:=dbedit_Nom.text;
     Obj_Client.prenom:=dbedit_Prenom.text;
    Soit tu utilises des DBControls et donc un TDataSet interne à l'objet accessible via un TDataSource
    Soit tu utilises des Controls non DB et tu fais tout à la main (un peu dommage !)
    Ne mélange pas le deux !

    Tu utilise ADO ou DBExpress ?

    Perso, j'ai pondu un mini couche sur DBExpress en C++Builder, j'ai un double mode, soit les objets soit chargés par RTTI soit utilise un DataSource, c'est selon le besoin !

    J'avais fait aussi une couche plus poussé gérant le modèle relationnel en Delphi, idem double mode, RTTI et DataSource
    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

  3. #3
    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
    C'est fou ce que la POO formate les esprits.

  4. #4
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 229
    Points : 60
    Points
    60
    Par défaut
    Merci pour votre reponse!
    Si je connais bien InstantObjects que j'ai utilisé mais je ne trouve pas ça très performant pour les grandes base de données.
    J'utilse ADO, je souhaiterais faire ça à la main en utilisant les procedures stockées car je veux mieux vérifier les données avant de les enregistrer dans la base.
    Si quelqu'un a une solution mieux d'adaptée il pourrait me faire savoir.
    Merci

  5. #5
    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 utilises des StoredProc ! Ouais ...
    Mon idée reste valable, cela ne change que la fonction Store qui déclenchera une exception en cas d'echec de la validation des données car non conforme

    Perso, j'ai toujours mis la logique métier dans le code de l'objet (une fonction Validate appelé par un équivalent de ton Store), c'est lui qui fait les contrôles. Ayant eu à maintenir des applications multi-DB, il était plus simple de coder le contrôle en Delphi que d'écrire le SQL de chacune des DB (IB, Oracle, MSSQL...)
    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

  6. #6
    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
    Citation Envoyé par Klemsy78 Voir le message
    Merci pour votre reponse!
    Si je connais bien InstantObjects que j'ai utilisé mais je ne trouve pas ça très ....
    Si quelqu'un a une solution mieux d'adaptée il pourrait me faire savoir.
    Merci
    Il y a également TIOPF, mais franchement, la VCL orienté données est à elle seule un Framework, il serait plus raisonnable de s'y tenir ou alors tu optes pour des produits fournis par RemObjects comme DataAbstract.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Février 2011
    Messages
    125
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 125
    Points : 78
    Points
    78
    Par défaut
    Bonjour à tous,
    je me permets de relancer cette discussion qui m'intéresse beaucoup....
    J'aimerai bien que d'autres personnes apportent leur avis pour expliquer leur méthode pour programmer objet et pas procédural avec Delphi dans une application de base de données...
    Moi j'ai tendance à faire du procédural et j'aimerai bien aller vers plus de programmation objet mais vu qu'en général j'utilise des DBGrid remplis par des Dataset je ne vois pas où insérer l'objet métier dans tout ça....
    Est-ce que quelqu'un aurait des ressources à proposer sur le sujet? je me dout qu'il est certainement question de la notion de Modèle Vue Contrôleur... mais celle-ci n'est pas forcément claire pour moi...
    Merci

  8. #8
    Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2006
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2006
    Messages : 229
    Points : 60
    Points
    60
    Par défaut
    J'ai essayé des framework metier tel que InstantObject,Bold qui permettent une bonne programmation orientée Objet sous Delphi7.
    Mais malheureusement j'ai été confronté à des problème de performance(temps de réponse...).
    Pour pallier donc à cela j'ai décidé d'implémenter ma propre couche Métier et ma couche d'Accès ce qui me permet d'interfacer ma Base de Données tout en gardant les performances du système de gestion de base de données.
    Voici un peu de façon générale comment je procède.

  9. #9
    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
    Le Gros problème des FrameWork OR c'est les collections d'objet, si tu as 10000 lignes, ils vont créer 10000 Objets, je préfère un système de curseur qui encaspule un DataSet pour les Listings !
    Idem, j'ai refait ma propre couche en 2007 en Delphi, depuis j'ai changé d'employeur, j'en repond une en C++Builder, c'est super fun à coder
    Maintenant est-ce utile ???
    Attention, on peut faire une couche métier où l'on fait tout manuellement dans chaque objet, mais la POO veut que l'on réutilise donc composition\héritage

    Sujets à lire
    Création de metaclass en dynamique
    Création d'objets "par lots"
    [BDD] Séparation de couche de données

    Le DBGrid n'est pas une limite !

    A Lire uniquement si vous avez envie de voir ce que cela peut amener de coder sa propre couche OR persistance avec tous les travers qui vont avec !
    Comme le disait le Sage :
    Citation Envoyé par chaplin Voir le message
    C'est fou ce que la POO formate les esprits.
    Dans mon cas, tous mes objets utilisent de la DB donc un TDataSet !

    Mes objets héritent tous du même ancêtre (TShaiORPersistent) qui fourni une propriété protégée DataSource !
    Je choisi dans l'héritier, si j'autorise la promotion en public (et donc implémente deux trois fonctions)

    Là ou je travaille, il y a déjà tout un système de gestion des liste, c'est la TFormListe qui gère via un DataModule interne, tout écran Liste hérite de cette forme abstraite (bon moi l'héritage de fenêtre, je ne pratique pas mais là je suis la méthode de la société)
    Mais, je voulais conserver une approche objet, donc dans ma fenêtre TFrmListeEnregistreurVideo héritant de TFormListe, dans le constructeur, j'ai

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      FObjEnregistreurVideo = new TShaiEnregistreurVideoMaterielEditor();
      FObjEnregistreurVideo->DataSource = ModuleData->DataSourceDBExpress; // L'Objet encapsule le Curseur sur l'Enregistrement actif du DataSet sous-jacent !

    le DataSet lié au DataSourceDBExpress peut contenir de 0 à n ligne selon le retour du SELECT (avec PacketRecords et tout le tralala)

    J'ai un bouton pour modifier un enregistrement qui va ouvrir un autre formulaire, au lieu de faire un truc

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void __fastcall TFrmListeEnregistreurVideo::BtnModificationClick(TObject *Sender)
    {
      // Modification   
      AfficheEnregistreurVideo(DBGrid->DataSource->DataSet->FieldByName('ID_EnregistreurVideo')->AsInteger);
    }
    J'ai ceci
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void __fastcall TFrmListeEnregistreurVideo::BtnModificationClick(TObject *Sender)
    {
      // Modification
      AfficheEnregistreurVideo(FObjEnregistreurVideo->PrimaryID);
    }
    Bon, cela ne révolutionne pas grand chose, juste lisibilité !

    Hiérarchie d'héritage (oui, je fais de l'héritage d'implémentation, oh oh là, ben oui en Delphi ça se fait, mais les ayatollah POO crieront au scandale)
    TShaiORPersistent > TShaiHardwareProviderAbstractPersistentObject > TShaiEnregistreurVideoCustom -> TShaiEnregistreurVideoMaterielEditor

    DataSourceDBExpress est aussi le DataSource qu'utilise la DBGrid fourni par TFormListe

    Lors que je me déplace dans la DBGrid, cela déplace le TDataSet associé, hors le TShaiORPersistent est utilisé en mode DataSource, exemple des propriétés ProviderID et FriendlyDeviceNumber du TShaiHardwareProviderAbstractPersistentObject, qui fonctionne presque de même façon que PrimaryID du TShaiORPersistent

    Code c++ : 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
     
    class TShaiHardwareProviderAbstractPersistentObject : public TShaiORPersistent, public IShaiHardwareLinkedDevice
    {
    private:
      // Membres Privés (propriétés publiées)
      int FFriendlyDeviceNumber;
     
      // Membres Privés
      TShaiHardwareProvider* FProvider;
     
    protected:
      int __fastcall GetProviderID();
      void __fastcall SetProviderID(int Value);
      int __fastcall GetFriendlyDeviceNumber();
      void __fastcall SetFriendlyDeviceNumber(int Value);
     
      // Propriétés Protégées pouvant être promues en Propriétés Publiques mais pas Publiées !
      __property TShaiHardwareProvider* Provider = {read=GetProvider};
     
    __published:
      // Propriétés Publiées
      __property PrimaryID; // Augmentation de Visibilité
      __property int ProviderID = {read=GetProviderID, write=SetProviderID};
      __property int FriendlyDeviceNumber = {read=GetFriendlyDeviceNumber, write=SetFriendlyDeviceNumber};
     
    public:
      static const AnsiString PROP_NAME_HPO_PROVIDER_ID;
      static const AnsiString PROP_NAME_HPO_FRIENDLY_DEVICE_NUMBER;
    };
    //---------------------------------------------------------------------------
    const AnsiString TShaiHardwareProviderAbstractPersistentObject::PROP_NAME_HPO_PROVIDER_ID = "ProviderID";
    const AnsiString TShaiHardwareProviderAbstractPersistentObject::PROP_NAME_HPO_FRIENDLY_DEVICE_NUMBER = "FriendlyDeviceNumber";
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class TShaiEnregistreurVideoMaterielEditor : public TShaiEnregistreurVideoCustom
     // donc hérite de TShaiHardwareProviderAbstractPersistentObject
    {
      // Propriétés Publiques
      __property DataSource; // Augmentation de Visibilité
      __property TShaiHardwareProvider* Provider = {read=GetProvider, write=SetProvider}; // Surcharge pour Write
    };
    Code c++ : 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
     
    //---------------------------------------------------------------------------
    void __fastcall TShaiEnregistreurVideoMaterielEditor::SetProvider(TShaiHardwareProvider* Value)
    {
      // On remplace par le nouveau
      Provider->Assign(Value); // Copie des propriétés de l'objet par RTTI !
      if (DataSource)
        FieldByPropertyName(PROP_NAME_HPO_PROVIDER_ID)->AsInteger = Value->PrimaryID;
    }
    //---------------------------------------------------------------------------
    /*override*/void __fastcall TShaiORPersistent::Assign(TPersistent* Source)
    {
      this->PrimaryID = -1;
     
      if (Source->InheritsFrom(__classid(TShaiORPersistent)))
      {
        this->DataSource = ((TShaiORPersistent*)Source)->DataSource;
        if ( ! this->DataSource)
          SetPublishedPropertiesFromPersistent(Source); // RTTI !
      }
      else if (Source->InheritsFrom(__classid(TDataSet)))
      {
        this->DataSource = NULL;
        SetPublishedPropertiesFromDataSet((TDataSet*)Source);
      }
      else
        inherited::Assign(Source);
    }
    les Accesseurs !
    Code c++ : 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
     
    //---------------------------------------------------------------------------
    TShaiHardwareProvider* __fastcall TShaiHardwareProviderAbstractPersistentObject::GetProvider()
    {
      if ( ! FProvider)
      {
        FProvider = new TShaiHardwareProvider(GetProviderManagerInstance()); // Lazy Loading !
      }
     
      return FProvider;
    }
     
    //---------------------------------------------------------------------------
    int __fastcall TShaiHardwareProviderAbstractPersistentObject::GetProviderID()
    {
      if (DataSource)
        LoadProviderByID(FieldByPropertyName(PROP_NAME_HPO_PROVIDER_ID)->AsInteger);
     
      return Provider->PrimaryID;
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TShaiHardwareProviderAbstractPersistentObject::SetProviderID(int Value)
    {
      LoadProviderByID(Value);
     
      if (DataSource)
        FieldByPropertyName(PROP_NAME_HPO_PROVIDER_ID)->AsInteger = Value;
    }
     
    //---------------------------------------------------------------------------
    int __fastcall TShaiHardwareProviderAbstractPersistentObject::GetFriendlyDeviceNumber()
    {
      return GetIntegerProp(FFriendlyDeviceNumber, PROP_NAME_HPO_FRIENDLY_DEVICE_NUMBER);
    }
     
    //---------------------------------------------------------------------------
    void __fastcall TShaiHardwareProviderAbstractPersistentObject::SetFriendlyDeviceNumber(int Value)
    {
      SetIntegerProp(FFriendlyDeviceNumber, Value, PROP_NAME_HPO_FRIENDLY_DEVICE_NUMBER);
    }
    les accesseurs génériques !

    Code c++ : 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
    //---------------------------------------------------------------------------
    void __fastcall TShaiORPersistent::SetIntegerProp(int &AIntegerMember, const int Value, const AnsiString &PropName/* = ""*/)
    {
      AIntegerMember = Value;
     
      if (DataSource)
        FieldByPropertyName(PropName)->AsInteger = AIntegerMember;
    }
     
    //---------------------------------------------------------------------------
    bool __fastcall TShaiORPersistent::GetBooleanProp(bool &ABooleanMember, const AnsiString &PropName/* = ""*/)
    {
      if (DataSource)
        ABooleanMember = FieldByPropertyName(PropName)->AsBoolean;
     
      return ABooleanMember;
    }
     
    //---------------------------------------------------------------------------
    TField* TShaiORPersistent::FieldByPropertyName(const AnsiString &PropertyName)
    //  throw(EShaiORPersistentPropertyFieldMappingError)
    {
      if (DataSource)
      {
        if (DataSource->DataSet)
          return DataSource->DataSet->FieldByName(FieldNameByPropertyName(PropertyName));
        else
          throw EShaiORPersistentPropertyFieldMappingError("DataSource->DataSet missing for Property %s of Class %s", PropertyName, this->ClassName()); // Pseudo-Assert Exception !
      }
      else
        throw EShaiORPersistentPropertyFieldMappingError("DataSource missing for Property %s of Class %s", PropertyName, this->ClassName()); // Pseudo-Assert Exception !
    }

    Eh ben, ça en fait du code pour un truc qui peut s'écrire en UNE SEULE Ligne !
    On a jamais dit que l'objet c'était léger !

    En tant que je troll, je code avec ma massue pour tasser le code et je force un peu si ça rentre pas ! ... disais le jeune marié ...

    Comme j'ai affecté un DataSource à mon objet, cela va lire le DataSet et non le membre privé qui ne sert à rien dans la situation actuel !

    C'était pour le listing même objet utilisé pour le formulaire de création ou de modification TFrmDetailEnregistreurVideo qui hérite du TFrmDetail
    TFrmDetail et TFormListe hérite tous les deux d'un TDataForm qui fourni le DataModule, j'utilise le mécanisme de chargement (le SELECT) qui existe

    dans le constructeur, un code similaire
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      FObjEnregistreurVideo = new TShaiEnregistreurVideoMaterielEditor();
      FObjEnregistreurVideo->DataSource = ModuleData->DataSourceDBExpress;
      FObjEnregistreurVideo->Edit();

    Cette fois le DataSet lié au DataSourceDBExpress ne contient qu'UNE SEULE UNIQUE ligne (ou rien du tout en cas de Création)

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    //---------------------------------------------------------------------------
    void TShaiORPersistent::Edit()
    {
      if (DataSource && DataSource->DataSet)
        DataSource->DataSet->Edit(); // Si l'ensemble de données est vide, Edit appelle Insert.
    }

    A Savoir que le DataSet est un TSimpleDataSet, en tout cas, tout est en mémoire !
    on peut faire pareil avec TClientDataSet ou les composants externe comme TMemoryDataSet, TVirtualDataSet ...

    Ensuite, j'utilise des ComboBox non DB, dont les Objects[] sont des objets ... qui sont aussi des TShaiHardwareProvider qui hérite du TShaiORPersistent !
    C'est ce que l'on ferait normalement avec un TDBLookupComboBox si l'on utilisait des DataSet directement !

    j'ai du code comme

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //---------------------------------------------------------------------------
    void __fastcall TFrmDetailEnregistreurVideo::ComboBoxProviderDVRChange(TObject *Sender)
    {
      FObjEnregistreurVideo->Provider = (TShaiHardwareProvider*)ComboBoxProviderDVR->Items->Objects[ComboBoxProviderDVR->ItemIndex];
    }

    Le Loup, c'est que l'on affecte un objet à une propriété du FObjEnregistreurVideo, plus haut, on a TShaiEnregistreurVideoMaterielEditor::SetProvider qui fait le boulot (utilise des ForeignKey, les relations Many-to-Many, c'est via des collections d'objet, pour le moment, je ne l'ai pas fait en C++Builder mais je l'avais fait il y a quelques années dans une autre société)


    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    //---------------------------------------------------------------------------
    void __fastcall TFrmDetailEnregistreurVideo::BtnValidationClick(TObject *Sender)
    {
      FObjEnregistreurVideo->Save();
    }

    Alors le code du Save, c'est de la génération de SQL via des RTTI ... déjà que j'en ai trop mis, je vais pas en rajouter, normalement tout le monde a arrêté de lire bien avant, seuls les fous sont venus jusque là, MickSou, j'espère ne pas t'avoir décourager !

    Enfin, dans un AUTRE programme, j'utilise ces TShaiEnregistreurVideo comme ceci

    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        FInternalDVR = new TShaiEnregistreurVideo();
        if (FInternalDVR->Load(CameraEntity->DVRPrimaryID))
        {
          ...
        }

    La Fonction Load va généer le SQL SELECT encore une fois avec de RTTI pour déterminer les Fields et le WHERE
    Par contre, Load ne conserve pas le DataSet, il va le lire une fois, remplir les propriétés publiées et donc les membres privés (donc les accesseurs SANS DataSource) et je peux utiliser mon objet tranquillement par la suite !

    bon Délire ! Non ?
    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

Discussions similaires

  1. Comment utiliser les données JSON dans un formpanel ?
    Par Nemesis007 dans le forum Ext JS / Sencha
    Réponses: 1
    Dernier message: 22/09/2010, 01h43
  2. Comment utiliser les données d'une base de données
    Par tresorkoul dans le forum JDeveloper
    Réponses: 8
    Dernier message: 10/07/2009, 14h47
  3. Réponses: 3
    Dernier message: 22/09/2007, 13h56
  4. Réponses: 3
    Dernier message: 05/05/2006, 11h41
  5. Réponses: 4
    Dernier message: 13/12/2004, 20h37

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