消防监控系统中动态配置ODBC数据源的VC程序实现

2018-11-01 05:19卢志强
电脑知识与技术 2018年18期
关键词:数据源

卢志强

摘要:面对客户提出的数据库中心需要由固定IP地址改为可动态修改的IP,以适应机房变更的需求,而且可能会在同一个应用程序中访问不同的数据库,作者在程序中自动完成这一工作的方法,快速满足了客户的需求。该文将详细介绍动态配置数据源的方法。

关键词:ODBC 数据源;动态配置;VC

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2018)18-0063-01

1 引言

本人项目组开发了某消防监控系统,采用VC开发实现,使用固定配置的ODBC数据源,而系统交付后遇到客户需求更改,提出原设计的数据库中心需要由固定IP地址改为可动态修改的IP,以适应机房变更的需求,而且可能会在同一个应用程序中访问不同的数据库,因此采用一般的加载方法就有了无法克服的缺陷。如果能在程序中自动完成这一工作,将能快速满足客户的需求。那么该如何通过程序代码完成数据源的注册呢?本文将详细介绍动态配置数据源的方法。

2 VC中加载数据源的具体实现

在VC中注册ODBC数据源一般有两种方法:利用函数SQLConfigDataSource和修改注册表。本文重点介绍利用函数SQLConfigDataSource的方法。

如果只是静态的配置ODBC数据源,即数据源各参数(数据源名称、服务器、数据库文件路径、数据库名等)是固定的,那么使用SQLConfigDataSource函数可以轻松的实现程序配置数据源,举例如下:

if(SQLConfigDataSource(NULL, ODBC_ADD_DSN, "SQL Server",

"DSN=EINet\0"

"SERVER=192.168.1.100\0"

"DATABASE=myEIfireDB\0"

"Trusted_Connection=Yes\0")==1)

AfxMessageBox("Success!");

上面的代码也可以写成:

if(SQLConfigDataSource(NULL, ODBC_ADD_DSN, "SQL Server", "DSN=EINet\0SERVER=192.168.1.100\0DATABASE=myEIfireDB\0Trusted_Connection=Yes")==1)

AfxMessageBox("Success!");

函數最后一个参数(lpszAttributes)为一连串的"KeyName = value"字符串,每两个KeyName值之间用""隔开,连续的两个引号,相当于连接符号,使用它们可以便于新代码排版,这比在行结尾处加连接符"\"更方便。lpszAttributes的具体设置,可以参考Windows系统目录下帮助文件odbcjtn.hlp主题目录标签中的“ODBC API函数改变|SQLConfigDataSource”条目。而尤其值得说明的是每个"KeyName = value"字符串都必须以"\0"结尾,这就造成了动态设定lpszAttributes的困难,先看这段代码:

CString strSource;

CString strIP = _T("192.168.1.100");

strSource.Format("DSN=EINet\0SERVER=\"%s\"\0DATABASE=myEIfireDB\0Trusted_Connection=Yes",strIP);

LPCSTR lpszAttributes = (LPCSTR)strSource;

if(SQLConfigDataSource(NULL,ODBC_ADD_DSN,"SQL Server",lpszAttributes)==1)

AfxMessageBox("Success!");

else

AfxMessageBox("Fail!");

运行结果:Fail!

单步调试观察变量变化:

发现lpszAttributes仅包含"DSN=EINet"的信息,其他配置数据源的信息都丢失了,原因在于CString默认以"\0"作为字符串的结束标志,在强制类型转换时造成了数据丢失。

解决办法为:使用编码转换,在堆栈中分配内存,创建一个char型数组,将lpszAttributes中的"\0"用"#"来表示,然后将数组中的字符赋给CString字符串,用CString的Replace方法再将"#"替换为"\0"。

具体代码如下:

BOOL AddDSN(CString strServerIP)

{

USES_CONVERSION;

_TCHAR buffer[MAX_PATH] = {0};

LPCTSTR lpstrServerIP = strServerIP;

_stprintf(buffer, _T("DSN= eiSource #")_T("SERVER=%s#") _T("DATABASE=eiDB#")_T("Trusted_Connection=Yes#"),lpstrServerIP);

CString strAttributes = buffer;

int len = strAttributes.GetLength();

strAttributes.Replace(_T('#'), _T('\0'));

return SQLConfigDataSource(NULL, ODBC_ADD_DSN, "SQL Server", strAttributes.GetBuffer(len));

}

上面两个函数中用到的USES_CONVERSION是ATL中的一个宏定义。用于编码转换(用的比较多的是CString的LPCWSTR转换)。在ATL下使用要包含头文件atlconv.h,使用时一定要小心,它们从堆栈上分配内存,直到调用它的函数返回,该内存不会被释放。如果在一个循环中,这个宏被反复调用几次,将不可避免的产生stackoverflow。为避免这种情况发生,同时减小代码量,在VC下可以更方便地直接使用下列代码:

BOOL ConfigDSN(CString strServerIP){

_TCHAR buffer[MAX_PATH] = {0};

LPCTSTR lpstrServerIP = strServerIP;

sprintf(buffer, _T("DSN= eiSource #")_T("SERVER=%s#") _T("DATABASE=eiDB#")_T("Trusted_Connection=Yes#"),lpstrServerIP);

CString strAttributes = buffer;

strAttributes.Replace(_T('#'), _T('\0'));

return SQLConfigDataSource(NULL, ODBC_CONFIG_DSN, "SQL Server", strAttributes);

}

调用上述自定义函数:

CString strServerIP = _T("192.168.1.100");

if(AddDSN(strServerIP))

AfxMessageBox("Success!");

执行代码后结果:Success!

可以看到,程序顺利地执行,成功配置好了数据源。

3 结束语

从以上分析和运行结果可以看出:利用函数SQLConfigDataSource和修改注册表,都可以实现动态修改数据源,尤其是可以实现多个数据源的切换,从而实现同一个应用程序中访问不同的数据库甚至通过IP地址切換实现访问同一数据源名的多个远程服务器。

猜你喜欢
数据源
基于神经网络编码的真值发现*
基于Spring Boot与MyBatis框架构建动态读写分离模型
基于Arc Engine的数据源更新系统的设计与实现
Web 大数据系统数据源选择*
Windows 7 64位平台下Oracle ODBC的配置
基于不同网络数据源的期刊评价研究
02C卫星成国土资源主体业务主力数据源
基于真值发现的冲突数据源质量评价算法
数据源总线化布局解决方案
分布式异构数据源标准化查询设计与实现