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 :

[BDD] Séparation de couche de données


Sujet :

Bases de données Delphi

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut [BDD] Séparation de couche de données
    Bonjour,

    je cherche à développer une application la plus générique possible et qui s'affranchirait au maximum du code spécifique à la base de données.

    Pour cela, je voudrais écrire des objets metiers qui recenseraient les fonctions principales de mon appli (ex : getListCeci, insertCela, DeleteCeluici) et dans lesquelles j adapterai le code en fonction d'une base access, mysql, sql server & co avec différents composants (ado, mysqldac etc....mais pas les dbexpress).

    Mon problème se situe à la restitution des données (en gros le DataSet du query).

    Je doute qu'il me soit possible de transtyper dans des TDataSet generique mes resultats ? donc je me demandais si finalement la meilleure solution ne serait pas d ecrire le resultat dans des fichiers XML et d en lire le contenu par la suite sachant que je ne travaille pas sur de gros volumes ( < 10 000) ?
    Niveau perf est ce que cest viable ?

    Quelles solutions me proposeriez vous ?

    Merci.

  2. #2
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    peut etre peux tu faire des objets qui retournent tes propres types.
    Par exemple :

    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
     
    type
      TUneTable = record
        UnChamp: integer;
        UnAutreChamp: string;
      end;
     
      TAccesBD = class
      public
        function GetCeci: TUneTable; virtual; abstract;
      end;
     
      TAccesBDAdo = class(TAccesBD)
      public
        function GetCeci: TUneTable; override;
      end;
     
      TAccesBDMySqlDac = class(TAccesBD)
      public
        function GetCeci: TUneTable; override;
      end;
     
    ...
     
    function TAccesBDAdo.GetCeci: TUneTable; 
    begin
      ici tu rempli le record a la maniere ADO
    end;
     
    ...

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    Merci

    solution interessante...


    Et tu listerais les structures dans une TList par exemple pour un ensemble de données ?

  4. #4
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    une TList ou alors un array. L'avantage de l'array, c'est que tu n'as pas besoin de caster ton contenu et ca prend moins d'espace memoire, l'inconvenient est que chaque modification de sa taille necessite un remappage complet en memoire. a toi de voir si tu as bcp de modifs de taille a faire ...

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 736
    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 736
    Points : 25 645
    Points
    25 645
    Par défaut
    Juste comme ça, le TClientDataSet associé à un Provider est fait pour transmettre des enregistrements sur la forme de tableau variants ou via XML, il y a bcp de sujet sur cela sur le forum, ainsi que des exemple sur le CD de Delphi ...

    Ensuite, tu as aussi la lib InstantObjects ... qui fait cela, tu as le Modèle ECO dans Delphi 2006 à ce que j'ai cru comprendre !

    Sinon, tu peux manipuler ton DataSet sans te préocupper de sa classe d'implémentation (sauf si tu veux optimiser en ne passant que par du SQL), normalement, ayant fait une couche d'abstraction objet aussi, je peux te dire que cela peut aller très loin, genre la gestion des valeurs nulles, l'héritage d'objet, les relations entre les objets ... tient pour te donner une idée de l'empleur, voici juste la partie interface de l'ancêtre de tous les objets métiers, ainsi que quelques autre classes (moi je suis allé très [trop) loin car je voulais faire un truc pouvant gérer du MySQL via SQL et du DBase via des Insert\Append, donc deux façons différentes de programmer ... mais c'était super fun à developper inutile mais fun )

    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
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    {* -----------------------------------------------------------------------------
    Thème : Modèle de Persistance (V2) 
    Unité : Classe de Base des Objets Metiers Persistants
    @author ShaiLeTroll
    @version 0.7
    ------------------------------------------------------------------------------ }
    unit uEpcPersistance;
     
    (* ATTENTION : le ClassManager ne supporte pas le Multi-Thread *)
    // Tester FastMM pour les Fuites Mémoire ...
     
    interface
     
    uses
       Windows, SysUtils, Classes, DB, Contnrs, Variants, Math, RTLConsts, Graphics, 
       uepcDBEntite,
       uEpcPersistanceTypes;
     
    type
      {*
      Type de l'ID d'un Persistant
      }
      TepcPersistantIDType = Int64;
      {*
      MétaClasse de TEpcPersistant (Référence de Classe)
      }
      TEpcPersistantClass = class of TEpcPersistant;
      {*
      Déclarations avancées de TEpcPersistantCollection
      }
      TEpcPersistantCollection = class;
      {*
      Déclarations avancées de TEpcPersistantRelation
      }
      TEpcPersistantRelation = class;
      {*
      Une Relation peut être une Clé Etrangère, une Relation N-N, une Relation N-N via une Classe
      }
      TEpcPersistantRelationType = (prForeignKey, prManyToMany, prObjectRelation);
      {*
      Déclarations avancées de TEpcPersistantClassList
      }
      TEpcPersistantClassList = class;
      {*
      Déclarations avancées de TEpcPersistantClassListItem
      }
      TEpcPersistantClassListItem = class;
      {*
      Evènement OnInitialize (voir TEpcPersistantClassManager.DoInitialize)
      }
      TPersistantInitializeEvent = procedure(const List: TEpcPersistantClassList; const XMLFileName: string; var Accept: Boolean) of Object;
      {*
      Binone ClassName / ClassType
      }
      TEpcPersistantRelationDescriptionClass = record
         ClassName: ShortString; // voir TObject.ClassName
         ClassType: TEpcPersistantClass;
      end;
      {*
      Pointeur sur TEpcPersistantRelationDescription
      }
      PEpcPersistantRelationDescription = ^TEpcPersistantRelationDescription;
      {*
      Descripteur de Relation, RelationType prend les Valeurs d'un TEpcPersistantRelationType, LazyLoad indique comment sont fait les lectures de la Base de Données, Detail indique la classe sur laquelle fait la relation pour une ForeignKey, Target indique la classe sur laquelle on devra lire les données issues de la relation extraite de RelationTableName pour une Relation N-N (ManyToMany), FirstRelationPart et SecondRelationPart se comporte comme une Double ForeignKey dans le Cas d'une Relation N-N via Classe sans se préoccuper de celle-ci
      }
      TEpcPersistantRelationDescription = record
        RelationType: TEpcPersistantRelationType;
        LazyLoad: Boolean;
        case TEpcPersistantRelationType of
        prForeignKey:
          (
          Detail: TEpcPersistantRelationDescriptionClass;
          );
        prManyToMany:
          (
          Target: TEpcPersistantRelationDescriptionClass;
          RelationTableName: string[255];
          );
        prObjectRelation:
          (
          FirstRelationPart: TEpcPersistantRelationDescriptionClass;
          SecondRelationPart: TEpcPersistantRelationDescriptionClass;
          );
      end;
      {*
      Contient les Données d'une Propriété Publiée
      }
      TEpcPersistantPropertyData = record
        OldValue: Variant;
        NewValue: Variant;
        PropertyType: Pointer; // via la Function TypeInfo(...);
        Changed: Boolean;
        Name: string;
      end;
      TEpcPersistantPropertyDataList = array of TEpcPersistantPropertyData;
      {*
      Classe de Base de Tous composants Persistants dans une Application Censure sur le Modèle de Persistance V2
      }
      TEpcPersistant = class(TComponent)
      private
        { Membres Privés }
        FTableName: string; /// Champ Interne, cf TableName
        FID: TepcPersistantIDType; /// Champ Interne, cf ID
        FIDName: string; /// Champ Interne, cf IDName
        FRelations: array of TEpcPersistantRelation; /// Champ Interne, cf Relations
        FRelationsToDo: TList;
        FData: TEpcPersistantPropertyDataList;
        FCollection: TEpcPersistantCollection;
        { Méthodes Privés }
        procedure _Initialize();
        procedure _Finalize();
        function AddRelationToDo(const RelationTableName: string; Master: TEpcPersistant; out ToDo: Pointer): Boolean;
        function AddRelationToSave(const RelationTableName: string; Master: TEpcPersistant): Boolean; overload;
        function AddRelationToSave(Relation, Master: TEpcPersistant): Boolean; overload;
        function AddRelationToDelete(const RelationTableName: string; Master: TEpcPersistant): Boolean;
        function AlterRelation(): Boolean;
        procedure InternalLoad(const NewID: TepcPersistantIDType);
        procedure InternalSave();
        function GetPropertyIndex(const PropertyName: string): Integer;
        function GetPropertyName(const Index: Integer): string;
        function GetPropertyData(const PropertyName: string): TEpcPersistantPropertyData;
        function RemoveCollection(): TEpcPersistantCollection;
        class function CreateCollection(): TEpcPersistantCollection;
        class function GetRelationDescription(const PersistantClass: TEpcPersistantClass): PEpcPersistantRelationDescription;
        class procedure CleanComponentProperties(List: TStrings);
      protected
        { Méthodes d'Accès }
        function GetItSelf(): TEpcPersistant;
        function GetPersistantClass: TEpcPersistantClass;
        function GetPersistantClassName: string;
        function GetRelations(const PersistantClass: TEpcPersistantClass): TEpcPersistantRelation;
        function GetPublishedProperty(const PropertyName: string): Variant;
        procedure SetPublishedProperty(const PropertyName: string; Value: Variant);
        function GetPublishedPropertyIsNull(const PropertyName: string): Boolean;
        function GetPublishedPropertyChanged( const PropertyName: string): Boolean;
        function GetPublishedPropertyType(const PropertyName: string): Pointer;
        function GetPublishedPropertyVarType(const PropertyName: string): TVarType;
        function GetIsAncestorClass: Boolean;
        function GetChanged: Boolean;
        { Méthodes d'Accès pour les Propriétés Indicées }
        function GetData(const Index: Integer): Variant; virtual;
        procedure SetData(const Index: Integer; const Value: Variant); virtual;
        { Propriétés Protégées }
        property Data[const Index : Integer]: Variant read GetData write SetData;
        { Propriétés Protégées à Publier !}
        property Relations[const PersistantClass: TEpcPersistantClass]: TEpcPersistantRelation read GetRelations;
      public
        { Constructeurs }
        constructor Create(AOwner: TComponent); overload; override;
        constructor Create(); reintroduce; overload; virtual;
        destructor Destroy; override; /// Destructeur surchargé d'un TComponent
        { Méthodes Publiques }
        procedure Assign(Source: TPersistent); overload; override;
        procedure Assign(Source: TPersistent; const Exclude: TStrings); reintroduce; overload; virtual;
        procedure AssignTo(Dest: TPersistent); overload; override;
        procedure AssignTo(Dest: TPersistent; const Exclude: TStrings); reintroduce; overload; virtual;
        class function Active: Boolean;
        class procedure RegisterMe();
        class function IsDebugger(): Boolean;
        class function Initialize(const XMLFileName: string; const OnInitialize: TPersistantInitializeEvent = nil): Boolean;
        class function InitializeBooleanValues(LocalIndex: Integer; const ATrueBoolStrs: array of string; const AFalseBoolStrs: array of string): Boolean;
        class function FindHerited(const ClassName: string): TEpcPersistantClass;
        class function PropertyCount: Integer;
        class function GetProperties(List: TStrings): Boolean;
        class function IsPublishedProperty(const PropertyName: string): Boolean;
        class function Load(const ID: TepcPersistantIDType): TEpcPersistant; overload;
        class function Load(const Keys: array of string; const Values: array of Variant): TEpcPersistant; overload;
        class function Load(Location: TPersistantProcLocation; const ProcName: string; const Values: array of const): TEpcPersistant; overload;
        class function Select(const Keys: array of string; const Values: array of Variant; OnlyOne: Boolean = False): TEpcPersistantCollection; overload;
        class function Select(const Keys: array of string; const Values: array of Variant; OnlyOne: Boolean; const Operators: array of TRelationalOperatorType): TEpcPersistantCollection; overload;
        class function Select(Location: TPersistantProcLocation; const ProcName: string; const Values: array of const; Index: Integer = 1; OnlyOne: Boolean = False): TEpcPersistantCollection; overload;
        function Fill(const Data: TDataSet): Boolean;
        function Save(): Boolean;
        function Delete(Cascade: Boolean = False): Boolean;
        function ToComponentString(): string;
        class function ComponentStringTo(Value: string): TEpcPersistant;
        class function RealAssigned(var Obj): Boolean;
        function StringToProperty(const PropertyName: string; const Value: string): Variant;
        function PropertyToString(const PropertyName: string): string;
        { Propriétés Publiques }
        property ItSelf: TEpcPersistant read GetItSelf;
        property TableName: string read FTableName; /// Nom de la Table Associée aux Persistants
        property ID: TepcPersistantIDType read FID; /// Identifiant Clé Primaire AutoIncrémenté Unique
        property IDName: string read FIDName; /// Nom de la Clé Primaire normalement "ID_TableName"
        property PersistantClass: TEpcPersistantClass read GetPersistantClass; /// Classe du Persistant
        property PropertyName[const Index: Integer]: string read GetPropertyName;
        property PublishedProperty[const PropertyName: string]: Variant read GetPublishedProperty write SetPublishedProperty;
        property PublishedPropertyIsNull[const PropertyName: string]: Boolean read GetPublishedPropertyIsNull;
        property PublishedPropertyChanged[const PropertyName: string]: Boolean read GetPublishedPropertyChanged;
        property PublishedPropertyType[const PropertyName: string]: Pointer read GetPublishedPropertyType;
        property PublishedPropertyVarType[const PropertyName: string]: TVarType read GetPublishedPropertyVarType;
        property IsAncestorClass: Boolean read GetIsAncestorClass; /// Classe utilisée comme Ancêtre ?
        property Changed: Boolean read GetChanged;
      published
        { Propriétés Publiées }
        property PersistantClassName: string read GetPersistantClassName; /// cf constante FIELD_CLASS_NAME
      end;
     
      {*
      Classe pour Lister d'Objets Persistants sous la Forme d'une Collection
      }
      TEpcPersistantCollection = class(TComponent)
      private
        { Membres Privés }
        FDataSet: TDataSet; /// DataSet Contenant les Objets
        FDataSource: TDataSource; /// DataSource pour afficher le DataSet
        FTableName: string; /// Identifie la Table sur laquelle la lecture des Objets a été faites
        FIDName: string; /// Identifie la Clé Primaire de la Table sur laquelle la lecture des Objets a été faites
        FDefaultClass: TEpcPersistantClass; /// Identifie la Classe par Défaut si le DataSet ne contient pas le Champ nommé FIELD_CLASS_NAME
        FPersistantList: TList;
        function CreateDefault(): TEpcPersistant;
        procedure ClearPersistantList();
        procedure NotifyDelete(const Persistant: TepcPersistant);
      protected
        { Méthodes d'Accès }
        procedure SetDataSet(Value: TDataSet); virtual;
        function GetIsEmpty(): Boolean; virtual;
        function GetCount(): Integer; virtual;
        function GetBOF(): Boolean; virtual;
        function GetEOF(): Boolean; virtual;
        function GetPersistant(): TEpcPersistant; virtual;
        function GetDataSource: TDataSource; virtual;
        function GetItems(Index: Integer): TEpcPersistant; virtual;
        { Méthodes Protégées }
        function GetPersistantOverload(RecNo: Integer): TEpcPersistant;
        procedure SetPersistantOverload(RecNo: Integer; var Value: TEpcPersistant);
        { Propriétés Protégées }
        property DataSet: TDataSet read FDataSet write SetDataSet; /// La Collection devient le Owner du DataSet !!!
        property TableName: string read FTableName write FTableName; /// Table correspond au DataSet
        property IDName: string read FIDName write FIDName; /// Clé Primaire de la Table correspond au DataSet
      public
        { Constructeurs }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy(); override;
        { Méthodes Publiques }
        procedure First(); virtual;
        procedure Last(); virtual;
        procedure Next(); virtual;
        procedure Prior(); virtual;
        procedure Delete(); overload; virtual;
        function Delete(const Persistant: TEpcPersistant): Boolean; overload; virtual;
        procedure Clear(); virtual;
        function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean; overload;
        function Locate(const Keys: array of string; const Values: array of Variant; Options: TLocateOptions): Boolean; overload;
        function Locate(const ID: TepcPersistantIDType): Boolean; overload;
        function Load(const ID: TepcPersistantIDType): TEpcPersistant; virtual;
        function ChangeFieldNames(const Names: array of string; const Labels: array of string): Boolean;
        { Propriétés Publiques }
        property IsEmpty: Boolean read GetIsEmpty; /// Détermine si un ensemble de données ne contient pas d'enregistrement.
        property Count: Integer read GetCount; /// Nombre de Persistant
        property BOF: Boolean read GetBOF; /// Début du DataSet
        property EOF: Boolean read GetEOF; /// Fin du DataSet
        property Persistant: TEpcPersistant read GetPersistant; /// Ligne Courante du DataSet converti en TepcPersistant
        property Items[Index: Integer]: TEpcPersistant read GetItems; default; /// Element de la Collection
        property DataSource: TDataSource read GetDataSource; /// Founit le DataSource qui consultera le DataSet Interne pour une Vue Grille
        property DefaultClass: TEpcPersistantClass read FDefaultClass write FDefaultClass; /// Indique le DataSource qui consultera le DataSet Interne pour une Vue Grille
      end;
     
      {*
      Classe pour Lier des Classes d'Objets Persistants
      }
      TEpcPersistantRelation = class(TEpcPersistantCollection)
      private
        { Membres Privés }
        FPersistantMaster: TEpcPersistant; /// Champ Interne, cf PersistantMaster
        FPersistantClass: TEpcPersistantClass; /// Champ Interne, cf PersistantClass
        FRD: PEpcPersistantRelationDescription; /// Champ Interne, contient la Description de la Relation
        FRelationLoaded: Boolean; /// Champ Interne, cf RelationLoaded
        FLazyLoaded: Boolean; /// Champ Interne, cf LazyLoaded
        FTheoricCount: Integer; /// Champ Interne, cf Count
        FRelationCountMode: Boolean; /// Champ Interne, cf Count
        procedure BeginRelationCount();
        procedure EndRelationCount();
      protected
        { Méthodes d'Accès }
        function GetCount(): Integer; override;
        function GetPersistant(): TEpcPersistant; override; // Attention à ceci !
        function GetDataSource: TDataSource; override;
        { Méthodes Protégées }
      public
        { Constructeurs }
        constructor Create(AOwner: TComponent); overload; override;
        constructor Create(const APersistantMaster: TEpcPersistant; const APersistantClass: TEpcPersistantClass); reintroduce; overload; virtual;
        { Méthodes Publiques }
        procedure First(ActionReload: Boolean = False); reintroduce; overload; virtual;
        procedure Last(ActionReload: Boolean = False); reintroduce; overload; virtual;
        function Load(const ID: TepcPersistantIDType): TEpcPersistant; overload; override;
        function Load(ActionFirst: Boolean = True; FullLoad: Boolean = False): TEpcPersistantRelation; reintroduce; overload; virtual;
        function Add(const Persistant: TEpcPersistant; const Relation: TEpcPersistant = nil): Boolean;
        function Delete(const Persistant: TEpcPersistant): Boolean; override;
        function Delete(): Boolean; reintroduce; overload; virtual;
        procedure Clear(); override;
        { Propriétés Publiques }
        property PersistantMaster: TEpcPersistant read FPersistantMaster; /// Identifie l'Instance de l'Objet Persistant à partir duquel on a extrait les Relations
        property PersistantClass: TEpcPersistantClass read FPersistantClass; /// Identifie la Classe Ancêtre des Objets extraits de la Relation
        property RelationLoaded: Boolean read FRelationLoaded; /// Indique que la Relation a au moins été chargé une fois
        property LazyLoaded: Boolean read FLazyLoaded; /// Indique que la Relation ne contient que les ID et non l'ensemble des Données
      end;
     
      {*
      Classe qui reprend l'ensemble des informations des Classes décrites dans le XML de Classes
      }
      TEpcPersistantClassList = class(TObjectList)
      public
        function IndexOf(const PersistantClass: TEpcPersistantClass): Integer;
      end;
     
      {*
      Classe qui reprend les informations des Classes décrites dans le XML de Classes, Correspond à un Element d'une TEpcPersistantClassList
      }
      TEpcPersistantClassListItem = class(TObject)
      private
        FTableName: string; /// Champ Interne, cf TableName
        FIsAncestorClass: Boolean; /// Champ Interne, cf IsAncestorClass
        FPersistantClass: TEpcPersistantClass; /// Champ Interne, cf PersistantClass
        FPersistantClassName: string; /// Champ Interne, cf PersistantClassName
        FProperties: TStrings; /// Champ Interne, cf Properties
        FRelationDescriptions: TList; /// Champ Interne, cf RelationDescriptions
        FPropertyData: TEpcPersistantPropertyDataList;
      public
        { Constructeurs }
        constructor Create();
        destructor Destroy(); override;
        { Méthodes Publiques }
        procedure Initialize(); overload;
        procedure Initialize(Persistant: TEpcPersistant); overload;
        procedure Finalize(Persistant: TEpcPersistant);
        { Propriétés Publiques }
        property TableName: string read FTableName write FTableName; /// Nom de la Table associé à un Persistant décrit le Fichier XML
        property IsAncestorClass: Boolean read FIsAncestorClass write FIsAncestorClass; // Indique si la Classe possède des Classes Heritées
        property PersistantClass: TEpcPersistantClass read FPersistantClass write FPersistantClass; // Classe du Persistant
        property PersistantClassName: string read FPersistantClassName write FPersistantClassName; // Nom de la Classe du Persistant décrit le Fichier XML
        property Properties: TStrings read FProperties; /// Liste des Proprités d'une Classe lue dans le Fichier XML
        property RelationDescriptions: TList read FRelationDescriptions; /// Liste des Relations d'une Classe Persistante décrites le Fichier XML
      end;
    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
       TCustomQueryAssistant = class(TObject)
       private
          { Méthodes Privées }
          class procedure FreeComponent(var Value: TComponent);
          class function IsTextValue(ValueType: TParamValueType): Boolean;
       public
          { Méthodes Publiques }
          class function Active: Boolean; virtual; abstract;
          class function GetClass(DBType: TepcDBType): TCustomQueryAssistantClass;
          class function GetConverter(DBType: TepcDBType): TCustomConverterAssistantClass;
          class function GetDBType: TepcDBType; virtual; abstract;
          class function GetStruct(TableName: string): TDataSet; virtual; abstract;
          class function GetStructQuery(TableName: string): string; virtual; abstract;
          class function GetTable(TableName: string): TDataSet; virtual; abstract;
          class function GetTableQuery(TableName: string): string; virtual; abstract;
          class function GetLastInsertID: Int64; virtual;
          class function GetNullStringValue: string; virtual; abstract;
          class function GetAlias(const Formule, AliasName: string): string; virtual; abstract;
          class function GetCountFormule(const AliasName: string): string; virtual; abstract;
          class procedure Initialize(); virtual; abstract;
          class procedure Finalize(); virtual; abstract;
          class procedure ExecuteScript(const QueryText: string; const Params: array of const); virtual; abstract;
          class function ExecuteQuery(const QueryText: string; const Params: array of const; OnlyOne: Boolean = False): TDataSet; virtual; abstract;
          class function ExecuteProc(const ProcText: string; const Params: array of const; OnlyOne: Boolean = False): TDataSet; virtual; abstract;
          class function BeginSelect(): TSelectAssistant; virtual;
          class function BeginInsert(): TInsertAssistant; virtual;
          class function BeginUpdate(): TUpdateAssistant; virtual;
          class function Select(const SelectFields: array of string; const TableName, Key: string; Value: Int64; OnlyOne: Boolean = True): TDataSet; overload; virtual; abstract;
          class function Select(const SelectFields: array of string; const TableName, Key, Value: string; const OrderByFields: array of string; out isEmpty: Boolean; Options: TSelectOptions = []; Limit: Integer = MAX_PACKET_RECORDS; StartIndex: Integer = 0): TDataSet; overload; virtual; abstract;
          class function Select(const SelectFields: array of string; const TableName: string; const Keys, Values: array of string; const OrderByFields: array of string; out isEmpty: Boolean; Options: TSelectOptions = []; Limit: Integer = MAX_PACKET_RECORDS; StartIndex: Integer = 0): TDataSet; overload; virtual; abstract;
          class function Select(const SelectFields: array of string; const TableName, Where: string; const OrderByFields: array of string; Limit: Integer = MAX_PACKET_RECORDS; StartIndex: Integer = 0; Options: TSelectOptions = []): TDataSet; overload; virtual; abstract;
          class function SelectEx(const SelectFields: array of string; const TableName: string; const Keys: array of string; const Relations: array of TRelationalOperatorType; const Values: array of Variant; const OrderByFields: array of string; out isEmpty: Boolean; Limit: Integer = MAX_PACKET_RECORDS; StartIndex: Integer = 0): TDataSet; overload; virtual; abstract;
          class function SelectEx(const SelectFields: array of string; const RelationTableName, TableName: string; const RelationKey, Key, MasterKey: string; Value: Int64): TDataSet; overload; virtual; abstract;
          class procedure Insert(const TableName: string; const SetKey, SetValue: string); overload; virtual; abstract;
          class procedure Insert(const TableName: string; const SetKeys, SetValues: array of string; Mode: TInsertMode); overload; virtual; abstract;
          class procedure Insert(const TableName: string; const SetKeys, SetValues: array of string; Mode: TInsertMode; const SetTypes: array of TParamValueType); overload; virtual; abstract;
          class procedure Insert(const TableName: string; const SetClause: string; Mode: TInsertMode); overload; virtual; abstract;
          class procedure Delete(const TableName: string; const Key: string; Value: Int64); overload; virtual; abstract;
          class procedure Delete(const TableName: string; const Key, Value: string; Options: TSelectOptions = []); overload; virtual; abstract;
          class procedure Delete(const TableName: string; const Keys, Values: array of string; Options: TSelectOptions = []); overload; virtual; abstract;
          class procedure Delete(const TableName, Where: string); overload; virtual; abstract;
          class procedure Update(const TableName: string; const SetKeys, SetValues: array of string; const Key: string; Value: Int64; const SetTypes: array of TParamValueType); overload; virtual; abstract;
          class procedure Update(const TableName: string; const SetKeys, SetValues: array of string; const Key, Value: string; const SetTypes: array of TParamValueType; Options: TSelectOptions = []); overload; virtual; abstract;
          class procedure Update(const TableName: string; const SetKeys, SetValues, Keys, Values: array of string; const SetTypes: array of TParamValueType; Options: TSelectOptions = []); overload; virtual; abstract;
          class procedure Update(const TableName: string; const SetKeys, SetValues: array of string; const Where: string; const SetTypes: array of TParamValueType); overload; virtual; abstract;
          class procedure Update(const TableName: string; const SetClause, Where: string); overload; virtual; abstract;
          class function MakeWhere(const Keys, Values: array of string; Options: TSelectOptions = []): string; overload; virtual; abstract;
          class function MakeWhere(const Keys, Values: array of string; const isText, AutoTrim: array of Boolean; Options: TSelectOptions = []): string; overload; virtual; abstract;
          class function MakeWhere(const Keys: array of string; Relations: array of TRelationalOperatorType; const Values: array of string): string; overload; virtual; abstract;
          class function MakeWhere(const Keys: array of string; Relations: array of TRelationalOperatorType; const Values: array of string; LogicalConnectors: array of TLogicalConnectorType): string; overload; virtual; abstract;
          class function MakeWhere(const Keys: array of string; Relations: array of TRelationalOperatorType; const Values: array of string; LogicalConnectors: array of TLogicalConnectorType; ValueType : array of TParamValueType): string; overload; virtual; abstract;
          class function MakeWhere(const Key: string; Relation: TRelationalOperatorType; LogicalConnector: TLogicalConnectorType; const Values: array of string; isText, AutoTrim: Boolean): string; overload; virtual; abstract;
          class function MakeWhere(const Keys: array of string; Relations: array of TRelationalOperatorType; const Values: array of string; LogicalConnectors: array of TLogicalConnectorType; isText, AutoTrim: array of Boolean): string; overload; virtual; abstract;
          class function CheckWhere(const Where, DefaultWhere: string): string; virtual; abstract;
          class function MakeCondition(const Key: string; Relation: TRelationalOperatorType; Value: string; isText: Boolean = False; AutoTrim: Boolean = False; CanEmptyValue: Boolean = True): string; virtual; abstract;
          class function MakeSet(SetKeys, SetValues: array of string; const SetTypes: array of TParamValueType): string; virtual; abstract;
          class function MakeValues(SetKeys, SetValues: array of string; const SetTypes: array of TParamValueType): string; virtual; abstract;
     
          class function ConnectCondition(const Condition, SubCondition: string; Connector: TLogicalConnectorType; AddEspace: Boolean = True): string; overload; virtual; abstract;
          class function ConnectCondition(const Condition, SubCondition, Connector: string; AddEspace: Boolean = True): string; overload; virtual; abstract;
          class function ConnectFields(const Fields, SubFields: string): string; virtual; abstract;
          class function ConnectTableFieldName(const TableName, FieldName: string): string; virtual; abstract;
          class function MakeFieldJoin(const TableName, FieldName: string): string; virtual; abstract;
     
          class procedure FreeDataSet(var Value: TDataSet); virtual;
          class procedure FreeDataSource(var Value: TDataSource); virtual;
          class function ChangeDataSet(var DataSet: TDataSet; const NewDataSet: TDataSet; const DataSource: TDataSource; ServerUpdate: Boolean): Boolean; virtual;
          class function ChangeLocalUpdate(const DataSet: TDataSet; LocalUpdate: Boolean): Boolean; virtual; abstract;
          class function IsLocalUpdate(const DataSet: TDataSet): Boolean; virtual; abstract;
          class function RecordCount(TableName: string): Integer; virtual; abstract;
       end;

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Août 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 165
    Points : 116
    Points
    116
    Par défaut
    Oula ca va trop loin pour moi la :p

    La solution de guillemouze me satisfait amplement je pense, maintenant je ne sais pas si je peux l appliquer facilement....

    Je voudrais developper au maximum du code de facon modulaire et generique.
    Je pensais que pour cela il serait mieux d utiliser des dll facon plugin, maintenant gerer la couche de donnees au milieu de tout cela me parait un peu obscure.

    Voici un exemple simple :

    Imaginons une appli qui charge dynamiquement une dll (purement delphi) qui integre une unite avec la partie graphique (un truc classique avec une petite image, 2 Tedit pour login password).
    Cette unite voudra verifier dans une bdd la coherence login/password par rapport aux infos inscrits dans une table.

    Pour se faire j imagine que la dll doit en appeler une autre qui contiendrait une fonction permettant elle meme d interroger la base de donnees (et cest la qu entreraient les objets metiers et la couche de donnees).

    Je ne suis pas donc bien sur que cela soit viable, surtout au niveau communication des objets utiles entre appli et dll voir dll a dll.

    Qqun a un point de vue a ce sujet ?

    Merci.


    nb: merci shailetroll en tout cas, je regarderai ton code plus en details qd je pourrais et que j en aurais plus le temps, ca me semble super interessant

  7. #7
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    J'utilise des scripts PHP pour l'accès aux bdd avec Delphi, justement pour séparer ces couches, sans compter les fonctionalités suplémentaires que peut apporter ce langage; Avec PHP, il existe par exemple PDO qui propose une interface d’abstraction pour l’accès aux différents types de SGBD (SQLite, MySQL, PostgreSQL, Oracle, Sybase, SQL Server, ... ).

    Dans mon tutoriel, j'utilise simplement MySQL, les requêtes étant en plus définies dans les scripts PHP... Mais dans le même principe, il est tout à fait possible d'utiliser PDO et d'émettre n'importe quelle requête avec Delphi.

    Actuellement, je suis en train de paufiner une nouvelle version plus "générique", avec plus de fonctionalités, un espace membre plus propre et sécurisé, mais il reste encore pas mal de boulot sur ce projet.

    A noter que Delphp est plus particulièrement adapté pour l'accès de bdd distantes (intranet ou internet), mais il fonctionne également en local.

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

Discussions similaires

  1. [N-Tier] Aide séparation en couche
    Par damien77 dans le forum Autres
    Réponses: 1
    Dernier message: 20/11/2008, 13h29
  2. Réponses: 3
    Dernier message: 26/12/2007, 11h34
  3. [MySQL] Lecture de données de la BDD et utilisation de ces données
    Par craac dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 03/12/2007, 16h10
  4. repaint() d'une seule couche de données
    Par seiryujay dans le forum Graphisme
    Réponses: 5
    Dernier message: 11/05/2006, 14h58
  5. [Design] Séparation des couches
    Par brousaille dans le forum Plateformes (Java EE, Jakarta EE, Spring) et Serveurs
    Réponses: 17
    Dernier message: 16/03/2005, 22h34

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