Comment conserver les informations d'état COM+ dans Delphi
Liu Xiaoming (chiffréliu)
Le problème commence ainsi : je dois écrire un COM+ pour me connecter à différentes bases de données. Certains amis diront peut-être qu'un COM+ devrait être établi pour chaque base de données, mais cela ne peut pas être fait dans mon système. Nous créons un système d'aide pédagogique et les utilisateurs sont des écoles (y compris les enseignants, les élèves et les parents de l'école, bien sûr). Nous construisons une base de données pour chaque école. Les structures de ces bases de données sont les mêmes. Bien entendu, nous disposons également d’une base de données de gestion pour coordonner les relations entre les bases de données. Chaque fois qu'un utilisateur scolaire est ajouté, nous activons une nouvelle base de données que le client peut utiliser. En d'autres termes, le nombre de nos bases de données augmente constamment et nous n'en développerons pas différentes pour chaque école. côté client, nous n'avons qu'un seul ensemble de COM+, au lieu de développer un ensemble pour chaque base de données. Je dois donc le laisser se connecter à différentes bases de données en fonction de l'identité de l'utilisateur dans COM+.
Évidemment, ce COM+ doit fournir une méthode pour permettre à son appelant (qui peut être une application client ou un autre middleware) de sélectionner la base de données à laquelle se connecter. En pratique, nous interrogeons la base de données dans la bibliothèque de gestion en fonction de l'ID de l'utilisateur. nom de la base de données, puis se connecte à la base de données utilisateur. Ici, afin de simplifier le problème, nous pensons que l'appelant connaît déjà le nom de la base de données, et demande directement à appeler cette base de données.
Ajoutez un membre privé DBName:string à la classe COM+ pour enregistrer le nom de la base de données à connecter. Nous devrions également fournir une telle méthode pour définir sa valeur. Je l'ai initialement écrit comme ceci.
PROcédure TmtsDBConn.ConnectTo(sDBName:string);
commencer
essayer
NomDB :=NomDB s;
EnsembleComplet ;
Sauf
SetAbort ;
fin;
fin;
Ensuite, placez-y les contrôles ADOConnection, ADODataSet et DataSetProvider, nommés respectivement adoc, adods et dsp. Définissez la relation de connexion entre eux, définissez la chaîne de connexion d'adoc sur la base de données de connexion "DB1", qui est la valeur par défaut, puis dans l'événement BeforeConnect d'adoc :
adoc.ConnectionString:=ConnectStringA+'Initial Catalog='+DBName+';'+ConnectStringC;
ConnectStringA et ConnectStringC sont ici des constantes de chaîne prédéfinies afin de construire dynamiquement la chaîne de connexion, comme suit :
const
ConnectStringA='Provider=SQLOLEDB.1;PassWord=2003;Persist Security Info=True;ID utilisateur=sa;';
ConnectStringB='Catalogue initial=DB1;';
ConnectStringC='Data Source=server3;Utiliser la procédure pour la préparation=1;Auto Translate=True;Packet Size=4096;Workstation ID=LXM;Utiliser le cryptage pour les données=False;Marquer avec le classement des colonnes lorsque cela est possible=False';
Compilez et installez ce COM+. Ensuite, écrivez un programme client pour l'appeler.
Placez un DCOMConnection dans le programme client, connectez-vous à celui-ci et écrivez le serveur COM+, placez un ClientDataSet, définissez ses propriétés RemoteServer et Provider, puis écrivez des instructions SQL dans son CommandText. Ensuite, insérez le contrôle DataSource et le contrôle DBGrid pour établir la connexion entre eux. Enfin mettez un bouton et dans son événement Click :
Dcomconnection1.Connected:=true;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active :=true ;
Dcomconnection1.Connected:=false;
Ce code sert à tester si les données de la base de données DB2 sont accessibles. Mais le résultat est qu'en cliquant sur le bouton, une erreur est toujours signalée. Quelle en est la raison ?
Revenez au projet COM+, déboguez-le, définissez des points d'arrêt dans ConnectTo et adocBeforeConnect et constatez que le programme s'exécute sur
NomDB :=NomDB s;
A l'exécution, la valeur de DBName a bien été fixée à "DB2", mais à l'exécution
adoc.ConnectionString:=ConnectStringA+'Initial Catalog='+DBName+';'+ConnectStringC;
, DBName est redevenu une chaîne vide, une erreur s'est donc produite.
Pourquoi la valeur de DBName est-elle perdue ? Il s'avère que la méthode SetComplete est appelée dans ConnectTo. La méthode SetComplete pense que COM+ a terminé la tâche et va libérer l'objet COM+. Par conséquent, lors de la connexion à la base de données, un nouveau COM+ est créé, et son DBName est bien sûr. nul. .
J'ai trouvé la raison, j'ai changé SetComplete en EnableCommit ; j'ai compilé, puis j'ai exécuté le client. Enfin, il s'est exécuté avec succès et a récupéré les données dans la base de données DB2.
Cependant, dans le programme client, j'ai mis un autre ClientDataSet. Après avoir ouvert ClientDataSet1, j'ai ouvert ClientDataSet2 et j'ai voulu continuer à accéder aux données dans DB2, mais une autre erreur a été signalée. Changez le programme en
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active :=true ;
ClientDataset1.Active :=false ;
ClientDataset1.Active :=true ;
Même si un seul ClientDataSet est utilisé, une erreur se produira toujours lors de sa réouverture après sa fermeture.
Mais si le client écrit
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active :=true ;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset2.Active :=true ;
Peut être exécuté avec succès. Mais cela semble très moche. Pourquoi COM+ se libère-t-il après la connexion à la base de données ?
Il s'avère que TmtsDataModule a un attribut AutoComplete et que la valeur par défaut est true, donc après s'être connecté à la base de données, il se publiera toujours.
Après avoir défini AutoComplete sur false, une erreur de suivi dans l'événement OnActivate de COM+ a révélé que lorsqu'il était activé, l'attribut AutoComplete était automatiquement défini sur true, donc après sa première connexion à la base de données, il serait toujours publié. lui-même.
Dans l'événement OnOnActivate de COM+, écrivez :
Saisie semi-automatique :=false ;
Il n'y a aucun problème si le client se connecte une fois et accède plusieurs fois à la base de données.
Mais dans ce cas, COM+ ne sera pas publié automatiquement. Vous devez ajouter une méthode à COM+, SetComplete dans cette méthode, puis appeler cette méthode pour libérer COM+ une fois que le client a terminé avec COM+.
Après l'exploration ci-dessus, nous sommes arrivés à la conclusion suivante : dans COM+, si vous souhaitez conserver les informations d'état, vous devez effectuer un certain travail, car COM+ est sans état par défaut. Chaque fois qu'il est appelé par le client, il jugera si. il doit se libérer tout seul, si nous ne voulons pas qu'il soit libéré, nous devons intervenir manuellement, et enfin nous devons le libérer manuellement.