Web 服务中的 Delphi dbGo

问题描述 投票:0回答:2

我正在尝试构建一个从 SQL Server 后端检索数据的 SOAP 服务器。我正在使用 Delphi 10.4 Community Edition 和 ADO 连接到数据库。我收到以下错误:未调用 CoInitialize。我理解这可能是因为Web Service是多线程的,线程需要调用这个函数。

我知道 DataSnap 可能是首选,但我真的想使用 ADO。

我的问题是在哪里调用这个函数,因为 TThread 对象没有在 Web 模块中公开。另外,我应该将 TADOTable 组件放在 DataModule 上还是可以放在 WebModule 中?

提前致谢。

windows delphi soap ado
2个回答
1
投票

谢谢弗雷迪。我能够连接到 WebService 并检索文件和数据集。我认为诀窍是将所有数据库内容放入 SOAPDataModule 中。我能够使用 ADODB(dbGO) 连接到 SQL Server 并检索记录。


0
投票

我主要是一名数据库开发人员。几年前我就决定使用驴子,我的大部分工作都集中在我已经知道如何使用的东西上(C++Builder、MSSQL 和 dbGo)。

从我收集到的点滴中...

我开发了许多使用 dbGo 的服务应用程序,这就是我了解 CoInitialize 的地方。在正常应用程序中您不会遇到这种情况,因为 CoInitialize 是由 Embarcadero 自动处理的。然而,根据 MS 文档,此调用会在当前线程上初始化 COM 库;因此,您在了解创建线程的同一天了解了 CoInitialize... 对我来说,这是我开始使用服务应用程序的时候。对于服务,似乎大多数建议建议不要使用“OnExecute”事件,而是创建一个在“OnStart”事件中启动并在“OnStop”事件中终止的线程。所以,我也遇到了 ADO、线程和 CoInitialize 方面的问题。

我发现我在哪里使用 CoInitialize 对它是否能正常工作有影响。如果我记得我尝试在明显的地方(线程构造函数)使用 CoInitialize 但这不起作用。起作用的地方是

'在 TMyThread::Execute () 块的开头'

注意:每次调用 CoInitialize 时,您还需要调用 CoUninitialize 一次。为了使实例跟踪更容易,我倾向于创建一个为我调用 CoInitialize(一次)的对象..并在清理后为我调用 CoUninitialize(一次)。

这是一个例子:对你来说不幸的是。我使用 C++ Builder 而不是 Delphi,但原理是相同的,所以这应该会有所帮助

TSimple_COMInitialise::TThread_COMInitialise ( void ) { CoInitializeEx(NULL,COINIT_MULTITHREADED); } TSimple_COMInitialise::~TThread_COMInitialise ( void ) { CoUninitialize(); } void __fastcall TWorkerThread_CC9000Sync::Execute () { // ( 'A Message' , show a timestamp ) this->SendSynchronisedFeedbackl (L"Thread::Begin Execution", true); // I use a pointer to a bool value so external threads can monitor // when the thread is running // apparently you can also use MyThreadObject->CheckTerminated(); externally this->_SetRunningStatus (true); // create an object that calls CoInitialize TSimple_COMInitialise *ptr_Thread_COMInitialise = new TSimple_COMInitialise(); __try { while (!this->Terminated) { //---- Add a wait/delay here ( to CPU usage reasonable ) ---- TThread::Sleep (this->ExecutePeriod); // request records from the SQL server and iterate through... this->DoWork_PROCESS_RECORDS(); this->DoWork_CALL_A_DIFFERENT_ADO_PROCEDURE(); if (this->Terminated) { this->SendSynchronisedFeedback (L"Thread::User Terminated", true); } } }__finally { // if this object in initiualised ... CoInitialize() was called if (ptr_Thread_COMInitialise) { // This will call CoUnInitialize() delete ptr_Thread_COMInitialise; }; } // let the main app know 'execute' has fully terminated/ended this->_SetRunningStatus (false); this->SendSynchronisedFeedback (L"Thread::End Execution", true); }

在我当前的项目中,我必须划分一些第三方组件,以避免它们因不兼容而相互冲突。我已将它们封装在 DataModules 中...所以我不知道使用数据模块是一个答案(我目前的“dbGo DataModule”有问题)。

也许 SOAP DataModule 中融入了一些 Embarcadero CoInitialize 魔法? 尽管如此,我无法找到它以便将其添加到我的项目中,所以它的可用性可能取决于项目类型。在这种情况下,对于任何无法使用 SOAP 模块的人...我希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.