在现代应用程序开发中,经常需要在不同的编程环境中进行数据访问。例如,未管理的C++应用程序可能需要通过Web服务访问数据库。本文将介绍一种方法,通过COM DLL(动态链接库)实现未管理代码调用ASP.NET Web服务的数据访问对象(DAO)。
在开始之前,需要了解为什么需要通过Web服务访问数据库,以及如何进行访问。同时,还需要知道如何创建托管代码的COM DLL,以及在未管理代码中调用COM DLL的方法。
首先,需要创建一个托管C#COM DLL,它将作为数据访问对象的实现。以下是创建COM DLL的步骤:
1. 定义一个接口IWebDatabaseAccessObject,用于外部调用函数。
[Guid("db0eef1a-22e2-4cc2-9a9c-58d5de4614ae")]
public interface IWebDatabaseAccessObject
{
// 定义接口方法...
}
2. 实现接口IWebDatabaseAccessObject的类WebDatabaseAccessObject。
[Guid("6ff59b6a-fb7e-4df6-9399-541ce0cd8632")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("WebDAO")]
public class WebDatabaseAccessObject : IWebDatabaseAccessObject
{
// 实现接口方法...
}
3. 创建一个函数,用于设置Web服务的Web服务器信息。
public string ConnectionString
{
get
{
return String.Format("{0}/{1}", strConnection.TrimEnd('/'), strWebServiceFileName);
}
}
4. 编写代码,请求SQL查询并从Web服务器获取结果数据,然后将数据赋值给System.Data.DataTable类型的变量。
public bool Open(string strSQL)
{
DSWebDAO.WebServiceDAO wsdWebServiceDAO = new DSWebDAO.WebServiceDAO();
wsdWebServiceDAO.Url = ConnectionString;
try
{
dtRecodeSet = wsdWebServiceDAO.GetRecodeSet(strSQL);
nRecodeIndex = 0;
}
catch
{
}
return (dtRecodeSet != null);
}
5. 需要在COM DLL中创建与ADO或DAO结构相似的成员函数。例如,MoveNext函数用于移动到Record-Set数据中的下一行,GetFieldValue函数用于获取所选行中每列的数据。
public bool MoveNext()
{
bool bReturnFlag = false;
if (dtRecodeSet != null)
if (bReturnFlag = (nRecodeIndex < dtRecodeSet.Rows.Count))
nRecodeIndex++;
return bReturnFlag;
}
接下来,需要创建一个未管理C++的包装类,以便调用托管C# COM DLL。生成类型库(tlb)文件后,可以像以下代码一样导入它。
#import "WebDAO.tlb" named_guids raw_interfaces_only
需要为类型库(tlb)文件创建一个包装类,并可以在包装类中插入额外的函数。例如,GetNumberByColumnNo函数将GetStringByColumnNo函数转换为获取数值类型的值。
CWebDAO::CWebDAO(CString strConnection)
{
bCOMInitailzed = Initialize();
BSTR bstrTemp = strConnection.AllocSysString();
m_pDotNetCOMPtr->SetConnectionString(bstrTemp);
SysFreeString(bstrTemp);
}
未管理C++应用程序必须调用CoInitialize函数来初始化和反初始化COM组件。
CoInitialize(NULL);
#ifdef _WEB_
CWebDAO recordSet(CDwUtility::GetWebDAOConnection());
#else
CDwAdoRecord recordSet(CDwUtility::GetDBConnection());
#endif
CString strSQL;
strSQL.Format("SELECT COUNT(*) AS EXAM_COUNT FROM T_CODE WHERE EXAM_KEY = %s", m_strExamKey);
BOOL bExamCount = FALSE;
if (recordSet.Open(strSQL))
{
while (recordSet.IsEOF() == FALSE)
{
int nCount;
recordSet.GetFieldValue(_T("EXAM_COUNT"), nCount);
bExamCount = (nCount > 0);
recordSet.MoveNext();
}
recordSet.Close();
}