Delphi에서 COM+ 상태 정보를 유지하는 방법
류샤오밍(劉孝命)
문제는 다음과 같이 시작됩니다. 다른 데이터베이스에 연결하려면 COM+를 작성해야 합니다. 어떤 친구들은 각 데이터베이스마다 COM+를 설정해야 한다고 말할 수도 있지만 내 시스템에서는 그렇게 할 수 없습니다. 우리는 교육 지원 시스템을 만들고 있으며, 사용자는 학교(물론 학교의 교사, 학생, 학부모 포함)입니다. 이러한 데이터베이스의 구조는 동일합니다. 물론 데이터베이스 간의 관계를 조정하는 관리 데이터베이스도 있습니다. 학교 사용자가 추가될 때마다 고객이 사용할 수 있는 새 데이터베이스가 활성화됩니다. 즉, 데이터베이스 수가 지속적으로 증가하고 있으며 각 학교마다 다른 데이터베이스를 개발하지 않습니다. 클라이언트 측에서는 각 데이터베이스에 대해 하나의 세트를 개발하는 대신 하나의 COM+ 세트만 보유합니다. 따라서 COM+의 사용자 ID를 기반으로 다른 데이터베이스에 연결하도록 해야 합니다.
분명히 이 COM+는 호출자(클라이언트 응용 프로그램 또는 기타 미들웨어일 수 있음)가 연결할 데이터베이스를 선택할 수 있도록 하는 방법을 제공해야 합니다. 실제로는 사용자 ID를 기반으로 관리 라이브러리의 데이터베이스를 쿼리합니다. 여기서는 문제를 단순화하기 위해 호출자가 이미 데이터베이스 이름을 알고 있다고 생각하고 이 데이터베이스를 직접 호출하도록 요청합니다.
COM+ 클래스에 전용 멤버인 DBName:string을 추가하여 연결할 데이터베이스의 이름을 저장합니다. 값을 설정하는 방법도 제공해야 합니다. 처음에는 이렇게 썼습니다.
PRocedure TmtsDBConn.ConnectTo(sDBName:string);
시작하다
노력하다
DB이름:=sDB이름;
설정완료;
제외하고
중단 설정;
끝;
끝;
그런 다음 ADOConnection, ADODataSet 및 DataSetProvider 컨트롤을 각각 adoc, adods 및 dsp라는 이름으로 배치합니다. 이들 사이의 연결 관계를 설정하고 adoc의 연결 문자열을 연결 데이터베이스 "DB1"(기본값)로 설정한 다음 adoc의 BeforeConnect 이벤트에서 다음을 수행합니다.
adoc.ConnectionString:=ConnectStringA+'초기 카탈로그='+DBName+';'+ConnectStringC;
여기서 ConnectStringA 및 ConnectStringC는 다음과 같이 연결 문자열을 동적으로 작성하기 위해 사전 설정된 문자열 상수입니다.
const
ConnectStringA='공급자=SQLOLEDB.1;PassWord=2003;보안 정보 유지=True;사용자 ID=sa;';
ConnectStringB='초기 카탈로그=DB1;';
ConnectStringC='데이터 소스=server3;준비 절차 사용=1;자동 번역=True;패킷 크기=4096;워크스테이션 ID=LXM;데이터 암호화 사용=False;가능한 경우 열 데이터 정렬을 사용하여 태그=False';
이 COM+를 컴파일하고 설치합니다. 그런 다음 이를 호출하는 클라이언트 프로그램을 작성하십시오.
클라이언트 프로그램에 DCOMConnection을 넣고 연결하여 COM+ 서버를 작성하고 ClientDataSet을 넣고 RemoteServer 및 Provider 속성을 설정한 다음 CommandText에 SQL 문을 작성합니다. 그런 다음 DataSource 컨트롤과 DBGrid 컨트롤을 넣어 둘 사이의 연결을 설정합니다. 마지막으로 버튼과 Click 이벤트를 추가합니다.
Dcomconnection1.Connected:=true;
Dcomconnection1.AppServer.connect('DB2');
ClientDataset1.Active:=true;
Dcomconnection1.Connected:=false;
이 코드는 DB2 데이터베이스의 데이터에 액세스할 수 있는지 테스트하는 것입니다. 그런데 결과적으로 버튼을 클릭하면 항상 오류가 보고됩니다. 이유는 무엇입니까?
COM+ 프로젝트로 돌아가서 디버깅하고 ConnectTo 및 adocBeforeConnect에 중단점을 설정한 다음 프로그램이 다음과 같이 실행되는지 확인합니다.
DB이름:=sDB이름;
실제로 실행시에는 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로 설정한 후에도 COM+의 OnActivate 이벤트 추적에서 오류가 계속 발생했습니다. 활성화되면 AutoComplete 특성이 자동으로 true로 설정되어 처음으로 데이터베이스에 연결된 후에도 여전히 해제됩니다. 그 자체.
COM+의 OnOnActivate 이벤트에서 다음을 작성합니다.
자동완성:=false;
클라이언트가 한 번 연결하고 데이터베이스에 여러 번 액세스하면 문제가 없습니다.
그러나 이 경우 COM+는 자동으로 해제되지 않습니다. COM+에 메서드를 추가하고 이 메서드에 SetComplete를 추가한 다음 클라이언트가 COM+ 사용을 마친 후 이 메서드를 호출하여 COM+를 해제해야 합니다.
위의 탐색 후에 우리는 다음과 같은 결론에 도달했습니다. COM+에서는 상태 정보를 유지하려면 몇 가지 작업을 수행해야 합니다. 왜냐하면 COM+는 기본적으로 클라이언트에서 호출될 때마다 여부를 판단하기 때문입니다. 자체적으로 릴리스해야 하며, 릴리스를 원하지 않으면 수동으로 개입해야 하며 마지막으로 수동으로 릴리스해야 합니다.