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 :

Problème avec ApplyUpdates ?


Sujet :

Bases de données Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut Problème avec ApplyUpdates ?
    Bonjour,

    Je développe une application multi-tier où j'ai l'erreur suivante lorsque j'essai un : ApplyUpdates(0) :
    Enregistrement introuvable, aucune clé spécifiée
    Savez-vous comment spécifier une clé et à quel endroit la mettre, dans quel composant, sur le client ou le serveur ?

    Serveur :
    - TADOConnection
    - TADODataSet
    - TDataSetProvider

    Client :
    - TSocketConnection
    - TClientDataSet
    - TDataSource

    Merci d'avance,
    Mathieu

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    J'ai trouvé la source de mon erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    FPrincipale.ClientDataSetRecherche.RefreshRecord;
    Je l'ai enlevé pour le moment car ApplyUpdates ne provoque aucunre erreur mais les données ne sont pas mises à jour...

    Que faire ?

    Merci d'avance,
    Mathieu

  3. #3
    Membre averti Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Points : 392
    Points
    392
    Par défaut
    Pour que le composant "TDataSetProvider" génère des requêttes de mise à jour optimisées, je vous conseil de suivre la procédure suivante:
    1 - pour chaque "DataSetProvider" mettre sa propriété "UpDateMode" à "upWhereKeyOnly".
    2 - pour chaque "ADODataSet", un champ clé (obligatoirement unique), et mettre la propriété du champ "ProviderFlags" = "[pfInUpDate,pfInWhere,pfInKey]".
    ....................................................................
    Aidez-vous... Dieu vous aideras et nous aussi..
    ....................................................................

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    J'ai suivi votre conseil qui marche très bien dans le cas d'une requête simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT * FROM MyTable
    Cependant, dès lors où j'utilise des jointures, aucune mise à jour s'effectue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT * FROM (MyTable A LEFT JOIN MyTable2 B ON A.Champ1=B.Champ1)
    LEFT JOIN MyTable3 C ON A.Champ1=C.Champ1 WHERE A.Champ1=xxxxx
    Je pense que la requête est trop compliquée pour que le composant effectue derrière une requête de mise à jour.

    Vous confirmez ?

    Merci,
    Mathieu

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    J'ai donc créé une suite de 3 composants pour interroger chaque table :
    TSocketConnection -> TClientDataSet -> TDataSource

    Par contre, lorsque j'applique mon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ClientDataSetInternet1.ApplyUpdates(0);
    ClientDataSetInternet2.ApplyUpdates(0);
    J'ai l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    09:19:28 -> SQL : SELECT * FROM mpg_BASE WHERE [Household ID]='33748'
    09:19:28 -> SQL : 
    09:19:28 -> ClientDataSetInternet2: Impossible d'effectuer cette opération sur un ensemble de données fermé
    Je remarque que mon ClientDataSetInternet2 n'a rien dans sa CommandText alors que j'ai bien les informations affichées sur mon formulaire...

    Voici le code que j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    constructor TFInternet.Create(AOwner: Tcomponent; Identifiant:string);
    begin
         inherited Create(AOwner);;
         try
              SocketConnectionInternet1.Address       := FPrincipale.ServeurIp;
              SocketConnectionInternet1.Port          := FPrincipale.ServeurPort;
              SocketConnectionInternet1.ServerName    := FPrincipale.InternetServerName;
              SocketConnectionInternet1.ServerGUID    := FPrincipale.InternetServerGUID;
              SocketConnectionInternet1.Connected     := true;
              ClientDataSetInternet1.CommandText      := 'SELECT * FROM mpg_BASE WHERE [Household ID]=' + QuotedStr(Identifiant);
              ClientDataSetInternet1.ProviderName     := 'DataSetProviderInternet';
              ClientDataSetInternet1.Active           := true;
     
              SocketConnectionInternet2.Address       := FPrincipale.ServeurIp;
              SocketConnectionInternet2.Port          := FPrincipale.ServeurPort;
              SocketConnectionInternet2.ServerName    := FPrincipale.InternetServerName;
              SocketConnectionInternet2.ServerGUID    := FPrincipale.InternetServerGUID;
              SocketConnectionInternet2.Connected     := true;
              ClientDataSetInternet2.CommandText      := 'SELECT * FROM mpg_STATUS WHERE [Household ID]=' + QuotedStr(Identifiant);
              ClientDataSetInternet2.ProviderName     := 'DataSetProviderInternet';
              ClientDataSetInternet2.Active           := true;
         except
              on E : Exception do
              begin
                   FPrincipale.Log('SQL : ' + ClientDataSetInternet1.CommandText);
                   FPrincipale.Log('SQL : ' + ClientDataSetInternet2.CommandText);
                   FPrincipale.Log(E.Message);
                   MessageDlg(E.Message, mtError, [mbOK], 0);
              end;
         end;
    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
     
    procedure TFInternet.SBEnregistrerClick(Sender: TObject);
    begin
         try
              ClientDataSetInternet1.ApplyUpdates(0);
              ClientDataSetInternet2.ApplyUpdates(0);
              Close();
         except
              on E : Exception do
              begin
                   FPrincipale.Log('SQL : ' + ClientDataSetInternet1.CommandText);
                   FPrincipale.Log('SQL : ' + ClientDataSetInternet2.CommandText);
                   FPrincipale.Log(E.Message);
                   MessageDlg(E.Message, mtError, [mbOK], 0);
              end;
         end;
    end;
    Pouvez-vous m'aider, je galère beaucoup là...

    Merci,
    Mathieu

  6. #6
    Membre averti Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Points : 392
    Points
    392
    Par défaut
    Je crois que le schéma d'organisation de votre application n'est pas correcte,
    Voici, normalement, comment cela doit être organisé :


    Application Client : TSocketConnection
    - TClientDataSet : « RemoteServer=SocketConnection », « DataSetProvider= DataSetProvider»
    - TDataSource : « DataSet =ClientDataSet»,


    Application Serveur : TADOConnection
    - TADODataSet : « Connection=ADOConnection », « CommandText=votre requette ».
    - TDataSetProvider : « DataSet=ADODataSet ».


    Pour le composant TClientDataSet, ne pas toucher sa propriété « CommandText ».
    Lorsque vous ouvrez un TClientDataSet, assurez-vous avant que son composant TADODataSet est ouvert lui aussi.
    Sachez aussi que le composant TClientDataSet, lorsqu'il est ouvert, il met ses données en mémoire, ce qui explique que même fermé il garde toujours la-dites données.
    Et enfin, les requêtes utilisées doivent être les plus simples possible.
    ....................................................................
    Aidez-vous... Dieu vous aideras et nous aussi..
    ....................................................................

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    J'ai en effet bien tout ça. La seule différence se trouve dans le CommandText que j'utilise sur le client et non le serveur via l'option suivante sur le TDataSetProvider->Options->poAllowCommandText.

    En fait, j'ai effectué des essais chez moi et ça fonctionne parfaitement. Or au travail, ça ne fonctionne pas.
    Quand je dis que ça ne fonctionne pas, le programme fonctionne correctement, seule les modifications ne sont pas effectuées...

    Je ne comprend pas pourquoi... Peut être un problème de droit car au travail je suis en réseau sur un domaine ?

    Merci,
    Mathieu

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    Après encore plusieurs tests, j'ai fait fonctionner mes deux petits programmes de client/serveur avec la grosse base de données.

    Conclusion : Les mises à jour ne sont pas prises en compte... cependant, si je mets une autre base toute simple, dans ce cas, les mises à jour sont appliquées.

    La table de ma grosse base de donénes sur laquelle je test l'application des mises à jour contient un peu plus de 17000 enregistrements.
    Le problème peut-il venir de là ?
    Si oui, comment faire ?

    Le problème semble être sur la base de données acr avec d'autres bases, ça fonctionne. Mais je ne sais pas ce qui peut empêcher la base de se mettre à jour...

    Avez-vous une idée ?

    Merci,
    Mathieu

  9. #9
    Membre averti Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Points : 392
    Points
    392
    Par défaut
    Est-ce que ton application affiche une erreur ?
    est-ce que l'accès à la base de donnée est autorisé ?
    est-que tu utilise une requète multi-tables ?
    pourquoi tu ne fait pas un essai avec la requete dans le "TADODataSet" ?
    quel base de données utilise-tu ?
    quel version de Delphi ?
    ....................................................................
    Aidez-vous... Dieu vous aideras et nous aussi..
    ....................................................................

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    Alors voici toutes les informations :
    Est-ce que ton application affiche une erreur ?
    => Aucune erreur lors de : ApplyUpdates. Mais pas de mise à jour des données...

    Est-ce que l'accès à la base de donnée est autorisé ?
    => Oui, lecture/écriture (Administrateur)

    Est-que tu utilises une requète multi-tables ?
    => Non, aucune jointure, de simple : SELECT * FROM MyTable WHERE Champ1='x'

    Quelle base de données utilises-tu ?
    => Microsoft Access 2000 (avec mot de passe) via un ODBC Microsoft Access Driver (*.mdb). J'ai vérifié si le problème pouvait venir du mot de passe sur une petite table de test, c'est pas le cas.

    Quelle version de Delphi ?
    => Borland Developer Studio 2006 Entreprise

    Pourquoi tu ne fais pas un essai avec la requête dans le "TADODataSet" ?
    => Parce que j'ai besoin de passer les requêtes que je veux via le client.

    J'ai vérifié un grand nombre de choses mais pour le moment je n'ai pas trouvé de solution...

    Je vais essayer de vérifier si le problème n'est pas causé par les espaces (" ") dans le nom des champs. Pour faire mon SELECT, je les encadre de crochets ("[Nom du champ]") mais le moteur lui, ne le fait peut être pas...

    Merci pour ton aide,
    Mathieu

  11. #11
    Membre averti Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Points : 392
    Points
    392
    Par défaut
    Donc, tu utilise une architecture Client/Serveur multi-niveau avec des applications clientes, un serveur d'application mais relié ACCESS qui n'est PAS un serveur de base de données !?
    je vous donne la difinition tiré de l'aide de Dephi:
    Dans sa forme la plus simple, parfois appelée "modèle à niveau triple", une application multiniveau est partitionnée en trois niveaux :

    Une application client : fournit une interface utilisateur sur la machine de l'utilisateur.
    Un serveur d'applications : réside dans un emplacement central du réseau, accessible à tous les clients, et offre des services de données courants.
    Un serveur de bases de données distant : supporte le système de gestion de base de données relationnelles (SGBDR).
    ....................................................................
    Aidez-vous... Dieu vous aideras et nous aussi..
    ....................................................................

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Salut,

    J'ai en effet :
    - Client applicatif
    - Serveur applicatif
    - Différentes base de données reliées à mon "Serveur applicatif" via un module de données distant : Microsoft Access 97, Microsoft Access 2000, SQL Server et Oracle.

    Mathieu

  13. #13
    Membre averti Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Points : 392
    Points
    392
    Par défaut
    Je crois qu'il vous faut changer de base de données et utiliser un vrai serveur de base de données et aussi utiliser les ADODataSet dans leurs véritables fonctions sinon à quoi il servent dans tout ça ?
    ....................................................................
    Aidez-vous... Dieu vous aideras et nous aussi..
    ....................................................................

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonjour,

    et aussi utiliser les ADODataSet dans leurs véritables fonctions sinon à quoi il servent dans tout ça
    Que voulez-vous dire avec cette phrase ?

    Comment les utiliseriez vous ?

    J'ai l'ajout qui marche mais pas la modification et l'enregistrement...
    C'est étrange...

    J'ai ajouté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    procedure TFHistoriqueContact.ClientDataSet1ReconcileError(
      DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind;
      var Action: TReconcileAction);
    begin
         MessageDlg(E.Message, mtError, [mbOK], 0);
    end;
    Et il me sort l'erreur suivante quand je fais un ApplyUpdates :
    Enregistrement non trouvé ou modifié par un autre utilisateur
    Edit1 :
    En cherchant sur le forum, je me suis rendu compte qu'il fallait que je mette la propriété UpdateMode à upWhereKeyOnly et que j'affecte mon champ dynamiquement via :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ADODataSetRecherche.FieldByName('IDENTIFIANT').ProviderFlags := [pfInKey];
    Cependant, je ne sais pas où placer ce code sur mon serveur... Le TADODataSet étant utilisé pour plusieurs tables, il me provoque une exception quand je le met dans le AfterOpen ou BeforePost...

    Que me conseilleriez-vous ?

    Merci,
    Mathieu

  15. #15
    Membre averti Avatar de Bejaia-In
    Inscrit en
    Avril 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 365
    Points : 392
    Points
    392
    Par défaut
    Citation Envoyé par Bejaia-In
    Pour que le composant "TDataSetProvider" génère des requêttes de mise à jour optimisées, je vous conseil de suivre la procédure suivante:
    1 - pour chaque "DataSetProvider" mettre sa propriété "UpDateMode" à "upWhereKeyOnly".
    2 - pour chaque "ADODataSet", un champ clé (obligatoirement unique), et mettre la propriété du champ "ProviderFlags" = "[pfInUpDate,pfInWhere,pfInKey]".
    Application Serveur : TADOConnection
    - TADODataSet : « Connection=ADOConnection », « CommandText=votre requête ».
    - TDataSetProvider : « DataSet=ADODataSet ».
    Je dois me citer pour vous rappeler que si vous n’utilisez pas nos réponses (ou du moins essayez) cela sert à rien de poser des questions.
    ....................................................................
    Aidez-vous... Dieu vous aideras et nous aussi..
    ....................................................................

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    73
    Détails du profil
    Informations personnelles :
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2006
    Messages : 73
    Points : 55
    Points
    55
    Par défaut
    Bonsoir,

    J'ai donc résolu mon problème qui n'était pas causé par le :
    La seule différence se trouve dans le CommandText que j'utilise sur le client et non le serveur via l'option suivante sur le TDataSetProvider->Options->poAllowCommandText.
    Le problème était causé par un champ de format "DATE" qui pose problème avec la clause WHERE. Informations trouvées ici :
    http://groups.google.fr/group/borlan...e0e6c7fc5621bf

    Merci,
    Mathieu

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

Discussions similaires

  1. ClientDataSet, problème avec ApplyUpdates ?
    Par djiga4me dans le forum Bases de données
    Réponses: 3
    Dernier message: 12/08/2011, 08h05
  2. Réponses: 4
    Dernier message: 17/03/2009, 12h25
  3. [D7][Access] Problème avec Clientdataset.ApplyUpdates
    Par Parrain dans le forum Bases de données
    Réponses: 1
    Dernier message: 09/08/2007, 19h09
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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