Как сохранить информацию о статусе COM+ в Delphi
Лю Сяомин (шифрлю)
Проблема начинается так: мне нужно написать COM+ для подключения к различным базам данных. Некоторые друзья могут сказать, что для каждой базы данных должен быть установлен COM+, но в моей системе этого сделать невозможно. Мы создаем систему помощи в обучении, а ее пользователями являются школы (включая учителей, учащихся и родителей, конечно же). Мы создаем базу данных для каждой школы. Структуры этих баз данных одинаковы. Конечно, у нас также есть база данных управления для координации отношений между базами данных. Каждый раз, когда добавляется пользователь школы, мы активируем новую базу данных для использования клиентом. Другими словами, количество наших баз данных постоянно увеличивается, и у нас есть только один клиент. Мы не будем разрабатывать разные базы данных для каждой школы. на стороне клиента у нас есть только один набор COM+ вместо разработки одного набора для каждой базы данных. Поэтому мне нужно разрешить ему подключаться к разным базам данных на основе личности пользователя в COM+.
Очевидно, что этот COM+ должен предоставлять метод, позволяющий вызывающей стороне (которым может быть клиентское приложение или другое промежуточное программное обеспечение) выбирать базу данных для подключения. На практике мы запрашиваем базу данных в библиотеке управления на основе идентификатора пользователя. имя базы данных, а затем подключаемся к пользовательской базе данных. Здесь, чтобы упростить задачу, мы думаем, что вызывающая сторона уже знает имя базы данных, и напрямую запрашивает вызов этой базы данных.
Добавьте закрытый член DBName:string в класс COM+, чтобы сохранить имя подключаемой базы данных. Мы также должны предоставить такой метод для установки его значения. Изначально я написал это так.
PROcedure TmtsDBConn.ConnectTo(sDBName:string);
начинать
пытаться
ИмяБД:=ИмяБД;
УстановитьЗавершить;
Кроме
УстановитьПрервать;
конец;
конец;
Затем поместите в них элементы управления ADOConnection, ADODataSet и DataSetProvider с именами adoc, adods и dsp соответственно. Установите связь между ними, установите строку подключения adoc к базе данных подключения «DB1», которая является значением по умолчанию, а затем в событии BeforeConnect adoc:
adoc.ConnectionString:=ConnectStringA+'Начальный каталог='+DBName+';'+ConnectStringC;
ConnectStringA и ConnectStringC — это предварительно установленные строковые константы для динамического построения строки подключения следующим образом:
константа
ConnectStringA='Provider=SQLOLEDB.1;PassWord=2003;Постоянная информация о безопасности=True;Идентификатор пользователя=sa;';
ConnectStringB='Исходный каталог=DB1;';
ConnectStringC='Источник данных=server3;Использовать процедуру для подготовки=1;Автоматическое преобразование=True;Размер пакета=4096;ID рабочей станции=LXM;Использовать шифрование для данных=False;Тег с сопоставлением столбцов, когда это возможно=False';
Скомпилируйте и установите этот COM+. Затем напишите клиентскую программу для ее вызова.
Поместите DCOMConnection в клиентскую программу, подключитесь к нему и напишите сервер COM+, поместите ClientDataSet, установите его свойства RemoteServer и Provider, а затем напишите инструкции SQL в его CommandText. Затем добавьте элементы управления DataSource и DBGrid, чтобы установить соединение между ними. Наконец, добавьте кнопку и в событии Click:
Dcomconnection1.Connected: = true;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active:=true;
Dcomconnection1.Connected:=false;
Этот код предназначен для проверки доступности данных в базе данных DB2. Но в результате при нажатии на кнопку всегда выдается сообщение об ошибке. В чем причина?
Вернитесь к проекту COM+, отладьте его, установите точки останова в ConnectTo и adocBeforeConnect и обнаружите, что программа выполняется
ИмяБД:=ИмяБД;
При выполнении значение DBName действительно было установлено на «DB2», но при выполнении
adoc.ConnectionString:=ConnectStringA+'Начальный каталог='+DBName+';'+ConnectStringC;
, DBName снова стало пустой строкой, поэтому произошла ошибка.
Почему значение DBName потеряно? Получается, что в ConnectTo вызывается метод SetComplete. Метод SetComplete думает, что COM+ выполнил задачу и освободит COM+-объект. Поэтому при подключении к базе данных создается новый COM+, и его DBName, естественно. нулевой. .
Я нашел причину, изменил SetComplete на EnableCommit, а затем запустил клиент. Наконец, он успешно запустился и получил данные в базе данных DB2.
Однако в клиентской программе я поставил другой ClientDataSet. После открытия ClientDataSet1 я открыл ClientDataSet2 и хотел продолжить доступ к данным в DB2, но была выдана другая ошибка. Измените программу на
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active:=true;
ClientDataset1.Active:=false;
ClientDataset1.Active:=true;
Даже если используется только один ClientDataSet, ошибка все равно возникнет при его повторном открытии после закрытия.
Но если клиент пишет
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active:=true;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset2.Active:=true;
Может быть успешно выполнено. Но это кажется очень некрасивым. Почему COM+ освобождается после подключения к базе данных?
Оказывается, у TmtsDataModule есть атрибут AutoComplete, а значение по умолчанию — true, поэтому после подключения к базе данных он все равно освободится.
После установки для AutoComplete значения false ошибка по-прежнему возникала. Отслеживание события OnActivate COM+ обнаружило, что при его активации атрибуту AutoComplete автоматически присваивалось значение true, поэтому после первого подключения к базе данных он все равно освобождался. сам.
В событии OnOnActivate COM+ напишите:
Автозаполнение:=ложь;
Нет проблем, если клиент подключается один раз и обращается к базе данных несколько раз.
Но в этом случае COM+ не будет освобожден автоматически. Вам необходимо добавить в этот метод метод SetComplete, а затем вызвать этот метод для освобождения COM+ после того, как клиент завершит работу с COM+.
После приведенного выше исследования мы пришли к следующему выводу: в COM+, если вы хотите сохранить информацию о состоянии, вам нужно проделать некоторую работу, поскольку COM+ по умолчанию не имеет состояния. он должен освободиться сам, если мы не хотим, чтобы он был выпущен, нам придется вмешаться вручную, и, наконец, мы должны освободить его вручную.