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 :

voir les modifs en mode multi utilisateur


Sujet :

Bases de données Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 14
    Par défaut voir les modifs en mode multi utilisateur
    Bonjour, je cherche à comprendre comment réaliser une application delphi/sqlserver multi-utilisateur ou les utilisateurs peuvent voir les modifications effectués par les autres utilisateurs ?!

    Pour cela je me suis connecté avec les composants ADO à la base Northwind fournit en exemple dans SQLServer (voir le code ci dessous).

    Problémes :
    Quand je lance 2 instances sur mon poste disons Inst1 et Inst2, si je modif un enregistrement dans le DBGrid1 de Inst1 alors DBGrid1 de Inst2 est aussi modifié (à condition de l'aider un peu en cliquant dessus, c'est pas top) mais si je modif DBGrid1 de Inst2 alors Inst1 quand à lui n'est pas modifié ?

    Manifestement je ne suis pas au point une âme charitable peut-elle m'aider à comprendre mes erreurs, Merci D'avance.

    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
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
     
      // connexion à la base de donnée "Northwind" fournit en exemple dans SqlServer
      with ADOConnection do
      begin
        ConnectionString := 'Driver={SQL Server}; ...';
        CursorLocation := clUseServer;
        IsolationLevel := ilUnspecified;
        LoginPrompt := False;
        Connected := True;
      end;
     
     // selection de la table "Region"
      with ADOTable do
      begin
        Connection := ADOConnection;
        CursorLocation := clUseServer;
        CursorType := ctKeyset;
        ReadOnly := False;
        TableDirect := True;
        TableName := 'dbo.Region';
        Active := True;
      end;
     
      // affichage de la table dans le DBgrid
      DataSource.DataSet := ADOTable;
      DBGrid1.DataSource := DataSource;     
     
    end;

  2. #2
    Membre chevronné
    Profil pro
    xxxxxxxxxxx
    Inscrit en
    Juin 2004
    Messages
    308
    Détails du profil
    Informations personnelles :
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : xxxxxxxxxxx

    Informations forums :
    Inscription : Juin 2004
    Messages : 308
    Par défaut Le serveur ne fait que répondre aux clients
    C'est un piège classique.
    Il ne faut pas croire que le serveur va "broadcaster" (envoyer une notification à tous ses clients connectés) pour avertir d'une modification d'un utilisateur vers tous les autres, susceptibles d'exploiter les mêmes données.
    Le CursorLocation clUseServer d'ADO peut lui aussi induire en erreur : Il ne faut pas en déduire qu'un curseur unique va être partagé entre les différents clients ; en réalité, chaque client va se créer un curseur stocké sur le serveur, représentant une image à un moment T des données souhaitées.
    La modification par le client 1 d'une donnée affichée par le client 2 n'aura donc de façon "live" aucun impact sur l'affichage du client 2. En revanche, dès que le client 2 va vouloir modifier à son tour la même donnée, il obtiendra une erreur lui indiquant que les données ont changé entre temps (et donc qu'il doit redemander les données à jour).
    Par expérience, 2 possibilités pour gérer l'accès concurrent :
    * le mode optimiste : le dernier qui validera ses données a raison, quitte à perdre la modification effectuée entre temps
    * le mode pessimiste : la première modification verrouille la donnée, qui devient indisponible pour tous les autres.

    Se rapprocher de la documentation d'SQL Server pour ce qui concerne le "niveau d'isolation des transactions" et la gestion des verrous (locks), sachant que Microsoft préconise des transactions courtes dans le temps pour limiter la consommation de ressources par les verrouillages.

  3. #3
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    En plus de ce que cmen76 à dit, j'ai mis un truc en place pour dispatcher les mis à jour au niveau de chaque client : chat inter-applicatif qui comprend :
    - un serveur qui va recevoir les messages d'un client et les dispatcher aux autres qui sont en ecoute.
    - les clients qui à chaque actions envoie le message vers le serveur pour en avertir les autres.
    Si la liaison vers le serveur est couper, je bascule en mode manuel ou via un timer pour le refresh.

    Voilà.

  4. #4
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 14
    Par défaut
    Merci "cmen76" pour ton explication très instructive. Je perçois un peu mieux les choses, j'ai donc essayé de réalisé un verrou pessimiste avec un curseur serveur sur ma fameuse table Région (bdd nothwind dans sqlserver). En particulier je n'ai pas pu affecter la propriété adoTable.IndexName avec la clé primaire de la table avec une erreur du genre le fournisseur ne supporte pas cette propriété. Je déposerai le source très prochainement pour étayer mais propos.

    Pour "Andry" stp une petite précision. Ta solution à l'air sympa mais je veux m'assurer de bien comprendre, il s'agit de la mise en place d'un serveur Udp, tes clients en + des leurs cnx à la base de données, notifies à chaque requête (delete, update ...) le serveur udp qui se charge de dispatcher l'infos de rafraîchissements des données aux autres clients connectés. Mais dans ce cas tous les clients exécutent un Refresh en même tps ? Si tu as a bcp de clients connectés et une bdd volumineuse y pas de pb ? Quels sont les avantages et inconvénient de ta méthode ?

  5. #5
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 236
    Par défaut
    Citation Envoyé par Zzapi
    Merci "cmen76" pour ton explication très instructive. Je perçois un peu mieux les choses, j'ai donc essayé de réalisé un verrou pessimiste avec un curseur serveur sur ma fameuse table Région (bdd nothwind dans sqlserver). En particulier je n'ai pas pu affecter la propriété adoTable.IndexName avec la clé primaire de la table avec une erreur du genre le fournisseur ne supporte pas cette propriété. Je déposerai le source très prochainement pour étayer mais propos.
    Déjà travailler avec des TAdoTable est une très mauvaise idée, il vaut mieux travailler avec des requetes.
    Sinon, il y a aussi les transactions (fortement conseillé surtout qu'elles fonctionnent très bien avec SQL server) qui permettent de gèrer les problèmes concurentiels.

    Petite explication : http://sql.developpez.com/sqlaz/techniques/
    Modérateur Delphi

    Le guide du bon forumeur :
    __________
    Rayek World : Youtube Facebook

  6. #6
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Par défaut
    Citation Envoyé par Zzapi
    stp une petite précision. Ta solution à l'air sympa mais je veux m'assurer de bien comprendre, il s'agit de la mise en place d'un serveur Udp, tes clients en + des leurs cnx à la base de données, notifies à chaque requête (delete, update ...) le serveur udp qui se charge de dispatcher l'infos de rafraîchissements des données aux autres clients connectés.
    Oui, tu as tout compris.
    Citation Envoyé par Zzapi
    Mais dans ce cas tous les clients exécutent un Refresh en même tps ? Si tu as a bcp de clients connectés et une bdd volumineuse y pas de pb ? Quels sont les avantages et inconvénient de ta méthode ?
    Bah en faites, ça dépends, seules les clients concernés seront mis à jour. Si par exemple, un message informe les clients qu'une update de la table XXX est effectué, seule les clients qui est en relation avec la table XXX est affecté, les autres ignorent le message.

    Voila

  7. #7
    Membre averti
    Inscrit en
    Septembre 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 14
    Par défaut
    Merci "Malatar" mais pourquoi il faut mieux pas utiliser TAdoTable ?
    Tu me conseilles donc d'utiliser TAdoQuery pour les requêtes qui retourne un résultats et TAdoCommand
    pour le reste (je vois pas a quoi sert TAdoCommand d'ailleurs car on peut tout faire TAdoQuery) ?

    Bon admettons que je veuille supprimer une ligne dans ma table Région mais il se pourrait que cette ligne
    soit déjà supprimée du fait d'un autre utilisateur, est ce que je peux le savoir avant de lancer la reqête de suppression ?

    Sinon comment faire pour ce type de code :
    - Connection avec un curseur serveur car multi utilisateur.
    - adoconnection.IsolationLevelil := ilRepeatableRead; (pour delete avec sqlserver).
    - LockType : ? je sais pas quoi mettre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        ADOConnection1.BeginTrans
        try
            AdoQuery.SQL.Add('Delete from region where IDRegion = 1');
            AdoQuery.Active:=True;
            ADOConnection1.Commit;
        except
          on e:exception do
          begin
            ADOConnection1.RollBack;
            AdoTable.Refresh;            // table region
          end;
        end;
    Dans ce cas la détection de la suppression de la ligne par un autre utilisateur se produit à posteriori, est ce une bonne façon de faire ?

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

Discussions similaires

  1. [conception] [07] mode multi-utilisateurs
    Par Temak31 dans le forum Modélisation
    Réponses: 5
    Dernier message: 23/04/2007, 17h05
  2. [Tableaux] Suivre les modifications faits par chaque utilisateur
    Par dessinateurttuyen dans le forum Langage
    Réponses: 7
    Dernier message: 19/07/2006, 10h05
  3. Blocage en mode multi-utilisateurs / multi-postes
    Par ruman dans le forum Access
    Réponses: 6
    Dernier message: 27/06/2006, 08h49
  4. Passage en Mode Multi-utilisateur
    Par joxbl dans le forum Requêtes
    Réponses: 1
    Dernier message: 30/11/2005, 23h15

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