Como manter informações de status do COM+ no Delphi
Liu Xiaoming (cifraliu)
O problema começa assim: preciso escrever um COM+ para conectar-me a diferentes bancos de dados. Alguns amigos podem dizer que deveria ser estabelecido um COM+ para cada banco de dados, mas isso não pode ser feito no meu sistema. Estamos fazendo um sistema de assistência educacional, e os usuários são escolas (incluindo professores, alunos e pais da escola, claro). Construímos um banco de dados para cada escola. Claro, também temos um banco de dados de gerenciamento para coordenar as relações entre os bancos de dados. Cada vez que um usuário escolar é adicionado, ativamos um novo banco de dados para uso do cliente. Ou seja, o número de nossos bancos de dados está aumentando constantemente e só temos um cliente. Não desenvolveremos bancos diferentes para cada escola. do lado do cliente, temos apenas um conjunto de COM+, em vez de desenvolver um conjunto para cada banco de dados. Então eu tenho que permitir que ele se conecte a diferentes bancos de dados com base na identidade do usuário no COM+.
Obviamente, este COM+ deve fornecer um método para permitir que seu chamador (que pode ser um aplicativo cliente ou outro middleware) selecione o banco de dados ao qual se conectar. Na prática, consultamos o banco de dados na biblioteca de gerenciamento com base no ID do usuário. nome do banco de dados e, em seguida, conecte-se ao banco de dados do usuário. Aqui, para simplificar o problema, pensamos que o chamador já conhece o nome do banco de dados e solicita diretamente a chamada desse banco de dados.
Adicione um membro privado DBName:string à classe COM+ para salvar o nome do banco de dados a ser conectado. Também devemos fornecer um método para definir seu valor. Inicialmente escrevi assim.
Procedimento TmtsDBConn.ConnectTo(sDBName:string);
começar
tentar
DBName:=sDBName;
DefinirCompleto;
Exceto
DefinirAbortar;
fim;
fim;
Em seguida, coloque os controles ADOConnection, ADODataSet e DataSetProvider neles, chamados adoc, adods e dsp respectivamente. Defina o relacionamento de conexão entre eles, defina a string de conexão do adoc para o banco de dados de conexão "DB1", que é o valor padrão, e depois no evento BeforeConnect do adoc:
adoc.ConnectionString:=ConnectStringA+'Catálogo Inicial='+DBName+';'+ConnectStringC;
ConnectStringA e ConnectStringC aqui são constantes de string predefinidas para construir dinamicamente a string de conexão, como segue:
const
ConnectStringA='Provider=SQLOLEDB.1;PassWord=2003;Persistir informações de segurança=True;ID do usuário=sa;';
ConnectStringB='Catálogo Inicial=DB1;';
ConnectStringC='Data Source=server3;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=LXM;Use Encryption for Data=False;Tag com agrupamento de colunas quando possível=False';
Compile e instale este COM+. Em seguida, escreva um programa cliente para chamá-lo.
Coloque um DCOMConnection no programa cliente, conecte-se a ele e grave o servidor COM+, coloque um ClientDataSet, defina suas propriedades RemoteServer e Provider e, em seguida, escreva instruções SQL em seu CommandText. Em seguida, coloque o controle DataSource e o controle DBGrid para estabelecer a conexão entre eles. Por fim coloque um botão e no seu evento Click:
Dcomconnection1.Connected:=true;
Dcomconnection1.AppServer.connect('DB2');
ClienteDataset1.Active:=true;
Dcomconnection1.Connected:=falso;
Este código serve para testar se os dados no banco de dados DB2 podem ser acessados. Mas o resultado é que ao clicar no botão sempre é reportado um erro. Qual o motivo?
Volte para o projeto COM+, depure-o, defina pontos de interrupção em ConnectTo e adocBeforeConnect e descubra que o programa é executado em
DBName:=sDBName;
Ao executar, o valor de DBName foi realmente definido como "DB2", mas ao executar
adoc.ConnectionString:=ConnectStringA+'Catálogo Inicial='+DBName+';'+ConnectStringC;
, DBName tornou-se uma sequência vazia novamente, portanto ocorreu um erro.
Por que o valor de DBName foi perdido? Acontece que o método SetComplete é chamado em ConnectTo. O método SetComplete pensa que o COM+ concluiu a tarefa e irá liberar o objeto COM+. Portanto, ao se conectar ao banco de dados, um novo COM+ é criado e seu DBName é, obviamente. nulo. .
Encontrei o motivo, alterei SetComplete para EnableCommit compilado e executei o cliente. Finalmente, ele foi executado com sucesso e recuperou os dados no banco de dados DB2.
Porém, no programa cliente, coloquei outro ClientDataSet. Após abrir o ClientDataSet1, abri o ClientDataSet2 e queria continuar acessando os dados no DB2, mas outro erro foi relatado. Mude o programa para
Dcomconnection1.AppServer.connect('DB2');
ClienteDataset1.Active:=true;
ClienteDataset1.Active:=falso;
ClienteDataset1.Active:=true;
Mesmo que apenas um ClientDataSet seja usado, um erro ainda ocorrerá quando ele for aberto novamente após ser fechado.
Mas se o cliente escrever
Dcomconnection1.AppServer.connect('DB2');
ClienteDataset1.Active:=true;
Dcomconnection1.AppServer.connect('DB2');
ClienteDataset2.Active:=true;
Pode ser executado com sucesso. Mas isso parece muito feio. Por que o COM+ é liberado após conectar-se ao banco de dados?
Acontece que TmtsDataModule possui um atributo AutoComplete e o valor padrão é true, portanto, após conectar-se ao banco de dados, ele ainda será liberado.
Após definir o AutoComplete como falso, ainda ocorreu um erro de rastreamento no evento OnActivate do COM+ que descobriu que quando ele foi ativado, o atributo AutoComplete foi automaticamente definido como verdadeiro, portanto, após conectar-se ao banco de dados pela primeira vez, ele ainda seria liberado. em si.
No evento OnOnActivate do COM+, escreva:
AutoCompletar:=falso;
Não há problema se o cliente se conectar uma vez e acessar o banco de dados diversas vezes.
Mas neste caso, o COM+ não será lançado automaticamente. Você precisa adicionar um método ao COM+, SetComplete neste método, e então chamar esse método para liberar o COM+ depois que o cliente terminar com o COM+.
Após a exploração acima, chegamos à seguinte conclusão: No COM+, se você deseja manter as informações de estado, é necessário fazer algum trabalho, pois o COM+ é sem estado por padrão. Cada vez que for chamado pelo cliente, ele julgará se. ele deveria se liberar sozinho, se não quisermos que ele seja liberado, temos que intervir manualmente e, finalmente, temos que liberá-lo manualmente.