FAQ DelphiConsultez toutes les FAQ

Nombre d'auteurs : 123, nombre de questions : 920, dernière mise à jour : 8 novembre 2019  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).

Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.

L'équipe Delphi de Developpez.com.

Commentez


SommaireBases de donnéesADO (5)
précédent sommaire suivant
 

Pour se connecter à des stockages de données ADO, nous devons spécifier des informations que nous fournissons à la propriété connectionString d'un composant ADO.
Lors de la conception, nous utilisons en général le Wizard qui construit automatiquement cette chaîne de connexion.

La fonction suivante permet de construire cette chaîne au runtime, uniquement pour les fournisseurs suivants : MS-SQL Server, Access, ODBC et ORACLE.
En cas d'erreur sur le nom du fournisseur, la fonction revoit la chaîne 'NONE'.

Code delphi : Sélectionner tout
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
uses 
  SysUtils, 
  Strutils; // AnsiIndexStr 
  
type 
TBuilder=record 
  ChaineConnexion : ShortString; 
  numeroTemplate  : Byte; 
end; 
  
Const 
NombreProvider=4; 
NombreTemplate=2; 
  
// Chaîne de connexion à construire 
Template : Array[1..NombreTemplate] of String = 
  ('Provider=%S;Persist Security Info=False;Password=%S;User ID=%S;Initial  
Catalog=%S', 
  'Provider=%S;Persist Security Info=False;Password=%S;User ID=%S;Data  
Source=%S' 
  ); 
  
// Nom des providers ADO 
Provider : Array[0..NombreProvider-1] of String= 
  ('SQLSERVER', 
   'ACCESS', 
   'ODBC', 
   'ORACLE' 
  ); 
// Informations utilisées dans la construction de la chaîne de connexion, cf. Template 
// Elles sont en correspondance avec l'indice du nom du provider. 
tabBuilder : Array [0..NombreProvider-1] Of TBuilder= 
  ((ChaineConnexion :'SQLOLEDB.1'; numeroTemplate :1),              // SQLSERVER 
   (ChaineConnexion :'Microsoft.Jet.OLEDB.4.0'; numeroTemplate :2), // ACCESS 
   (ChaineConnexion :'MSDASQL.1';numeroTemplate :2),                // ODBC 
   (ChaineConnexion :'MSDAORA.1';numeroTemplate :2)                 // ORACLE 
  ); 
  
function buildConnexionString(Fournisseur,Base,User,PassWord: string):string; 
var Monprovider :Integer; 
begin 
  Monprovider:=AnsiIndexStr(Fournisseur, Provider); 
  If Monprovider >= 0 then 
   with tabBuilder[Monprovider] do 
    Result := Format(Template[numeroTemplate],[ChaineConnexion,Password,User,Base]) 
  else raise Exception.Create(Format('Le fournisseur %s est inconnu.',[Fournisseur])); 
end;
Utilisation :
Code delphi : Sélectionner tout
1
2
ADOConnection1.ConnectionString :=  
  buildConnexionString('ODBC','MaBaseNameAliasODBC','UserName','MotDePasse');
Construit la chaîne de connexion en utilisant le gestionnaire de bases de données ODBC pour une base se nommant MaBaseNameAliasODBC et dont les identifiants de connexion sont UserName et MotDePasse.

Mis à jour le 18 janvier 2014 Laurent Dardenne Pascal Jankowski

L'utilisation d'ADO revient à utiliser un ensemble de composants COM.
Il est nécessaire pour les applications d'initialiser la bibliothèque COM avant d'utiliser ces composants.

Si l'initialisation n'a pas eu lieu, dès la première utilisation d'un objet ADO, une exception sera levée avec pour message "CoInitialize n'a pas été appelé".

Une application initialise COM grâce à

Code delphi : Sélectionner tout
Application.Initialize;
que l'on retrouve automatiquement dans le DPR. C'est ce qui vous a sûrement amené à utiliser ADO sans jamais avoir initialisé la bibliothèque COM.

Il existe néanmoins des cas où l'initialisation n'est pas automatique, comme entre autre une application Service NT, une DLL, une application WebSnap.
Afin d'initialiser COM, on utilisera alors
Code delphi : Sélectionner tout
CoInitialize(nil);
avant d'utiliser les objets ADO et
Code delphi : Sélectionner tout
CoUnInitialize;
afin de clore l'utilisation de la bibliothèque COM. Ces appels nécessitent d'ajouter ActiveX dans les Uses.

Dans le cas d'un Service NT par exemple, on placera l'instruction CoInitialize dans l'événement ServiceStart, et l'instruction CoUnInitialize dans l'événement ServiceStop. L'utilisation des objets ADO se fera entre ces deux appels.

Dans le cas d'une application console, l'appel de CoInitialize doit être contenu dans le corps de l'application console, et non dans une procédure ou une fonction au risque de déclencher une violation d'accès.

Mis à jour le 18 janvier 2014 NoisetteProd

Pour afficher la boite de configuration d'ADO et ainsi pouvoir construire la chaine de connexion à une base de données comme vous le feriez en conception :

  • Il faut rajouter dans les clauses uses, l'unité AdoConEd
  • Utiliser la commande EditConnectionString

Ci-dessous, un petit exemple :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
procedure ConfigurerAdo; 
begin 
  AdoConnection .Connected := False;//Ou utiliser l'équivalent AdoConnection.Close; 
  EditConnectionString(AdoConnection); 
  try 
    AdoConnection .Connected := True;//Ou utiliser l'équivalent AdoConnection.Open; 
  Except on E:Exception do 
    Showmessage(E.Message); 
  end; 
end;
Ceci ne sauvegarde pas les modifications que vous effectuez sur la chaine de connexion, c'est à vous de gérer par la suite le chargement/sauvegarde de cette dernière.

Sinon, une autre méthode, plus complète existe. Elle a pour avantage de récupérer la chaîne de configuration.
Code delphi : Sélectionner tout
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
Uses ...,OleDB, ComObj, ActiveX,... 
  
... 
implementation 
... 
  
function ADOConnectionString(ParentHandle:THandle;InitialString:WideString;out NewString: string): Boolean; 
var 
  DataInit: IDataInitialize; 
  DBPrompt: IDBPromptInitialize; 
  DataSource: IUnknown; 
  InitStr: PWideChar; 
begin 
  Result   := False; 
  DataInit := CreateComObject(CLSID_DataLinks) as IDataInitialize; 
  if InitialString <> '' then 
    DataInit.GetDataSource(nil,CLSCTX_INPROC_SERVER,PWideChar(InitialString),IUnknown, DataSource); 
  DBPrompt := CreateComObject(CLSID_DataLinks) as IDBPromptInitialize; 
  if Succeeded(DBPrompt.PromptDataSource(nil, ParentHandle, 
    DBPROMPTOPTIONS_PROPERTYSHEET, 0, nil, nil, IUnknown, DataSource)) then 
  begin 
    InitStr := nil; 
    DataInit.GetInitializationString(DataSource, True, InitStr); 
    NewString := InitStr; 
    Result    := True; 
  end; 
end; 
  
procedure TForm1.Button1Click(Sender: TObject); 
var 
  initst, nexstr : string; 
begin 
  initst := 'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=MonLogin;Initial Catalog=MaBdd;Data Source=MonServeur'; 
  if ADOConnectionString(form1.Handle,initst, nexstr) then 
    MessageDlg(nexstr, mtWarning, [mbOK], 0); 
end;
Il est également possible de remplacer la fonction ADOConnectionString par la fonction PromptDataSource de l'unité ADODB.
Code delphi : Sélectionner tout
Function PromptDataSource(ParentHandle: THandle; InitialString: WideString): WideString;
Utilisation :
Code delphi : Sélectionner tout
PromptDataSource(0, ADOConnection.ConnectionString);

Mis à jour le 18 janvier 2014 NoisetteProd Rayek

Il peut parfois s'avérer très utile d'exporter une table ADO dans un format plus "universel" que le format natif. Voici deux méthodes qui vous permettront d'importer et d'exporter une table "ADO" au format *.XML.

Vous noterez la concision du code qui se passe de commentaire ainsi que sa vélocité.

Code delphi : Sélectionner tout
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
Unit Import_Export_Ado_Xml; 
interface 
  
uses 
  Classes, 
  ADOInt; 
  
function TableVersXML(const Atable: _Recordset): String; 
function TableDepuisXML(const XML: String): _Recordset; 
  
implementation 
  
uses 
  ComObj; 
  
function TableVersXML(const Atable: _Recordset): String; 
var 
  VT        : Variant; 
  AStream    : TStringStream; 
begin 
  Result     := ''; 
  if Atable   = nil then Exit; 
  AStream  :=TStringStream.Create(''); 
  try 
    VT := CreateOleObject('ADODB.Recordset'); 
    VT := ATable; 
    VT.Save(TStreamAdapter.Create(Astream) as IUnknown, adPersistXML); 
    AStream.Position:= 0; 
    Result     := AStream.DataString; 
  finally 
    AStream.Free; 
  end; 
end; 
  
function TableDepuisXML(const XML: String): _Recordset; 
var 
  VT : Variant; 
  AStream : TStringStream; 
begin 
  Result := nil; 
  if XML = '' then Exit; 
  try 
    AStream := TStringStream.Create(XML); 
    AStream.Position:= 0; 
    VT := CreateOleObject('ADODB.Recordset'); 
    VT.Open(TStreamAdapter.Create(AStream) as IUnknown); 
    Result := IUnknown(VT) as _Recordset; 
  finally 
    AStream.Free; 
  end; 
end; 
  
end.
Exemple d'utilisation :
Nous supposerons que vous avez créé une fiche principale nommée "Form1" munie d'un TMemo nommé "Memo1", 2 TButton nommés "Button1", "Button2" ainsi que d'un TADOquery nommé "Adoquery1". Adoquery1 est connecté à votre base de données via sa propriété ConnectionString ; sa requête, pour "MaTable" étant : "SELECT MaTable.* FROM MaTable"
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 
Uses 
... 
Import_Export_Ado_Xml; 
// 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
  Memo1.Lines.Text := TableVersXML(ADOQuery1.Recordset); //Exportation  
end; 
  
procedure TForm1.Button2Click(Sender: TObject); 
begin 
  ADOQuery1.Recordset := TableDepuisXML(Memo1.Lines.Text); //Importation 
end;
  • Fonctionne avec TADOTable, TADOQuery, TADODataSet
  • Dans le cas de traitement par lot, veillez à sauvegarder toutes vos tables sous des noms différents sous peine de lever une exception pour cause de structure de table incompatible.
  • Fonctionne avec pratiquement tout ce qui est connectable via les composants ADO
  • Fonctionne avec toutes les versions de Access depuis la version 97 jusqu'à 2007
  • Travaille avec tout type de champs. Cependant, dans le cas d'une table volumineuse, les champs Blob rendront vite votre fichier "balourd".
  • Triez, filtrez vos données et utilisez ces fonctions en lieu et place d'un TBatchMove pour ADO

Mis à jour le 18 janvier 2014 Hauwke

ADO propose, sur les classes dérivées de TCustomADODataSet, la propriété Recordset de type interface _Recordset.
Cette interface donne accès à l'ensemble des enregistrements et propose la méthode GetString permettant de récupérer ses données dans un WideString.

Voici comment récupérer, au format CVS, un _RecordSet ADO dans une chaîne de caractères de type WideString :

Code delphi : Sélectionner tout
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
type 
  ESaveDataSetNoData = Class(Exception); 
  EDictionnaireVide=Class(Exception); 
  
  
const 
  COLUMNDELIMITER = ';'; 
  MsgNoData='Aucune donnée.'; 
  
{*------------------------------------------------------------------------------ 
Renvoie le contenu d'un RecordSet ADO au format CSV. Attention à la taille des données renvoyées. 
Le Header ( nom des champs sur la première ligne) n'est pas géré. 
  @param ARecordSet   RecordSet ADO 
  @param StringFormat   Format d'export : adClipString 
  @param ColumnDelimiter   Séparateur de champ 
  @param RowDelimiter   Séparateur de ligne 
  @param NullExpr   Expression pour les valeur de champ à NULL 
  @return Une chaîne contenant l'intégralité d'un RecordSet ADO au format CSV 
------------------------------------------------------------------------------*} 
Function SaveDataSetCSV(ARecordSet : _Recordset; StringFormat: StringFormatEnum; 
                        const ColumnDelimiter: WideString; const RowDelimiter: WideString; 
                        const NullExpr: WideString): WideString; 
begin 
  Result := ''; 
  //Récupère, au format CSV, l'intégralité d'un dataset dans une string 
  With ARecordSet do 
  begin 
    if RecordCount = 0 then 
      Raise ESaveDataSetNoData.Create(MsgNoData); 
    Result := GetString(StringFormat, RecordCount, ColumnDelimiter, RowDelimiter, NullExpr); 
  end; 
end;
L'exception ESaveDataSetNoData indique qu'il n'existe pas de données, les autres exceptions pouvant survenir seront gérées dans les traitements appelant.

Ensuite il est aisé de l'enregistrer dans un fichier :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{*------------------------------------------------------------------------------ 
Ecrit, au format CSV, le contenu d'un RecordSet ADO dans un fichier. Attention à la taille des données renvoyées. 
S'il existe déjà un fichier portant ce nom, il est ouvert en mode écriture. 
  @param AADOARecordSet   RecordSet ADO 
  @param AFilename   Nom du fichier CSV 
------------------------------------------------------------------------------*} 
Procedure SaveDataSetTo(AADOARecordSet : _Recordset; AFilename :TFileName); Overload; 
var 
  AllData: string; 
  Liste : TStringList; 
begin 
   // Repositionne le curseur pour enregistrer l'intégralité des données. 
  AADOARecordSet.First; 
  Liste := TStringList.Create; 
  try 
   Liste.Text := SaveDataSetCSV(AADOARecordSet, adClipString, COLUMNDELIMITER, sLineBreak, ''); 
   Liste.SaveToFile(AFilename); 
  finally 
    Liste.Free; 
  end; 
end;
Ou de l'enregistrer dans une liste de chaînes :
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{*------------------------------------------------------------------------------ 
Ecrit, au format CSV, le contenu d'un RecordSet ADO dans une TStrings existante. Attention à la taille des données renvoyées. 
La liste est remise à zéro avant l'opération. 
  @param AADOARecordSet   RecordSet ADO 
  @param AList   Liste de chaîne hébergeant les lignes du RecordSet 
------------------------------------------------------------------------------*} 
Procedure SaveDataSetTo(AADOARecordSet : _Recordset; AList: TStringList);Overload; 
  
begin 
  // obligatoire sinon la récupération des données ne se fera 
  // qu'à la position courante du curseur dans la base de données: 
  MoveFirst; 
  AList.Text := SaveDataSetCSV(AADOARecordSet, adClipString, COLUMNDELIMITER, sLineBreak, ''); 
end;
Voici un exemple d'appel pour enregistrer le résultat d'un requête dans une liste de chaînes:
Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
var Dictionnaire : TStringList 
begin 
  ...//Creation de la requête 
  try 
    SaveDataSetTo(Query.Recordset,Dictionnaire); 
  except 
    on ESaveDataSetNoData do 
    Raise EDictionnaireVide.Create('Le dictionnaire de recherche est vide'); 
  end; 
  ... 
end;
Déclarez :
  • l'unité System pour accéder à la constante sLineBreak
  • l'unité ADOint pour accéder à la constante adCliping et au type StringFormatEnum.

Note : Cette approche ne permet pas de traitement sur les données à exporter.

Mis à jour le 18 janvier 2014 Laurent Dardenne Rayek

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2019 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.