关于解决VS2008ODBC连接MySQL时“绑定所有列“程序崩溃问题
2012-04-20 13:55
531 查看
2012年5月20更新:
1. 连Oracle没有这个问题,修改了标题
2.可以使用VC6生成这些东西,不过和VS2008生成的有一些不同。
==============
这两天做数据库实验,VS2008连接MySQL数据库的时候,或者添加类的时候,每次勾选“绑定所有列”都会导致VS2008崩溃,上网一番搜索也没找到什么合适的解决方式。找到的一些文章都是建议手工绑定。
虽然我用的表不超过十个,每个表里的属性也不超过十个,不过总觉得手工去建立一个一个CRecordSet的派生类,再自己在*.h添加变量,在*.cpp添加诸如“RFX_Text(pFX, _T("location"), m_location);”这样的句子实在是太麻烦了……
于是自己写了一个小小的代码生成器来完成这项工作。其实思路很简单,就是读取*.sql文件里的create table部分,参照VS2008 Class Wizard自动生成对应的*.h和*.cpp,生成对应的*.h和*.cpp文件。分别为table对应的CRecordSet的派生类。之后把这些文件都拷贝到VS2008工程的文件夹里,添加到项目中就可以了。
生成器是按照自己写*.sql的习惯来写的,主要是方便自己使用,所以对sql文件有做了几个小限制:
1. 使用生成代码器前把create table替换成createtable
2. table名字不包括“XXXXXXXX”,因为这个作为占位符放在sample.h和sample.cpp中供复制文件时替换
3. 目前只支持varchar和int类型,因为我暂时只需要这两个,不过扩展起来很方便
4. 习惯性写法“create table tablename( ...”中tablename后加一个括号,然后换行,所以代码生成器中直接去掉括号得到tablename
要手工改一下*.cpp里初始化部分的n_Fields……
如果发现新添加的这些类没有基类型,手工用Class Wizard添加一个CRecordSet的派生类再删掉就可以了。
代码草草加了一些注释,贴上来吧。
sample.h和sample.cpp是VS2008 Class Wizard自动生成的CRecordSet的派生类对应的文件修改而来的。拆成两部分,中间部分正好是用来添加变量或者是RFX_Text之类的。
sample1.h
sample1.cpp
sample2.h
sample2.cpp
1. 连Oracle没有这个问题,修改了标题
2.可以使用VC6生成这些东西,不过和VS2008生成的有一些不同。
==============
这两天做数据库实验,VS2008连接MySQL数据库的时候,或者添加类的时候,每次勾选“绑定所有列”都会导致VS2008崩溃,上网一番搜索也没找到什么合适的解决方式。找到的一些文章都是建议手工绑定。
虽然我用的表不超过十个,每个表里的属性也不超过十个,不过总觉得手工去建立一个一个CRecordSet的派生类,再自己在*.h添加变量,在*.cpp添加诸如“RFX_Text(pFX, _T("location"), m_location);”这样的句子实在是太麻烦了……
于是自己写了一个小小的代码生成器来完成这项工作。其实思路很简单,就是读取*.sql文件里的create table部分,参照VS2008 Class Wizard自动生成对应的*.h和*.cpp,生成对应的*.h和*.cpp文件。分别为table对应的CRecordSet的派生类。之后把这些文件都拷贝到VS2008工程的文件夹里,添加到项目中就可以了。
生成器是按照自己写*.sql的习惯来写的,主要是方便自己使用,所以对sql文件有做了几个小限制:
1. 使用生成代码器前把create table替换成createtable
2. table名字不包括“XXXXXXXX”,因为这个作为占位符放在sample.h和sample.cpp中供复制文件时替换
3. 目前只支持varchar和int类型,因为我暂时只需要这两个,不过扩展起来很方便
4. 习惯性写法“create table tablename( ...”中tablename后加一个括号,然后换行,所以代码生成器中直接去掉括号得到tablename
要手工改一下*.cpp里初始化部分的n_Fields……
如果发现新添加的这些类没有基类型,手工用Class Wizard添加一个CRecordSet的派生类再删掉就可以了。
代码草草加了一些注释,贴上来吧。
/* CRecordSet派生类产生器 团子 2012年4月20日 sql文件要求: 处理前先把"create table"换成createtable table名后换行 暂时只处理varchar和int类型,别的有需要再加 假设table不会叫"XXXXXXXX" */ #include <string> #include <iostream> #include <fstream> using namespace std; const string output_dir="res\\"; //输出文件夹 const string sqlfilename="lab2_gen.sql"; //*.sql文件 const string suffix="set"; //类名=C+tablename+suffix string tablename; //当前处理的table的名字+suffix void copytofile(ofstream &dst, const char* filename) { ifstream src(filename); if (!src.is_open()) { printf("%s 未找到!\n", filename); return; } int pos; string tmp; while (getline(src, tmp)) { while ((pos=tmp.find("XXXXXXXX", 0))!=string::npos) { tmp.replace(pos, 8, tablename.c_str()); } dst<<tmp<<endl; } src.close(); } int main() { string str[2]; ofstream res_h, res_cpp; freopen(sqlfilename.c_str(), "r", stdin); int now=0, pre=1; str[pre]=""; while (cin>>str[now]) { const char* strpre=str[pre].c_str(); const char* strnow=str[now].c_str(); if (str[pre].find("createtable", 0)==0) { str[now].replace(str[now].find("(", 0),1,""); //如果习惯性写法中table名之后连着括号 tablename=str[now]+"set"; string hname=output_dir+tablename+".h"; string cppname=output_dir+tablename+".cpp"; printf("build %s %s\n", hname.c_str(), cppname.c_str()); res_h.open(hname.c_str(), ios::out); res_cpp.open(cppname.c_str(), ios::out); if (!res_h.is_open() || !res_cpp.is_open()) { printf("输出文件打开失败!\n"); return 0; } copytofile(res_h, "sample1.h"); copytofile(res_cpp, "sample1.cpp"); } if (str[now].find("varchar", 0)==0) { //变量名以m_开头 res_h<<"\tCString m_"<<str[pre]<<";"<<endl; res_cpp<<"\tRFX_Text(pFX, _T(\""<<str[pre]<<"\"), m_"<<str[pre]<<");"<<endl; } else if (str[now].find("int", 0)==0) { //变量名以m_开头 res_h<<"\tint m_"<<str[pre]<<";"<<endl; res_cpp<<"\tRFX_Int(pFX, _T(\""<<str[pre]<<"\"), m_"<<str[pre]<<");"<<endl; } //else if ... 如果要添加对更多类型的支持,这里可以相应扩展 if (str[now].find(");", 0)==0) { copytofile(res_h, "sample2.h"); copytofile(res_cpp, "sample2.cpp"); res_h.close(); res_cpp.close(); } now=1-now; pre=1-pre; } return 0; }
sample.h和sample.cpp是VS2008 Class Wizard自动生成的CRecordSet的派生类对应的文件修改而来的。拆成两部分,中间部分正好是用来添加变量或者是RFX_Text之类的。
sample1.h
// XXXXXXXX.h : CXXXXXXXX 的声明 #pragma once // 由团子的code_gen生成~ class CXXXXXXXX : public CRecordset { public: CXXXXXXXX(CDatabase* pDatabase = NULL); DECLARE_DYNAMIC(CXXXXXXXX); // 字段/参数数据
sample1.cpp
// XXXXXXXX.h : CXXXXXXXX 类的实现 // CXXXXXXXX 实现 // 由团子的code_gen生成~ #include "stdafx.h" #include "XXXXXXXX.h" IMPLEMENT_DYNAMIC(CXXXXXXXX, CRecordset) CXXXXXXXX::CXXXXXXXX(CDatabase* pdb) : CRecordset(pdb) { m_nFields = 0; m_nDefaultType = dynaset; } CString CXXXXXXXX::GetDefaultConnect() { return _T("换掉我"); //换成自己的 } CString CXXXXXXXX::GetDefaultSQL() { return _T(""); } void CXXXXXXXX::DoFieldExchange(CFieldExchange* pFX) { pFX->SetFieldType(CFieldExchange::outputColumn);
sample2.h
// 以下字符串类型(如果存在)反映数据库字段(ANSI 数据类型的 CStringA 和 Unicode // 数据类型的 CStringW)的实际数据类型。 // 这是为防止 ODBC 驱动程序执行可能 // 不必要的转换。如果希望,可以将这些成员更改为 // CString 类型,ODBC 驱动程序将执行所有必要的转换。 // (注意: 必须使用 3.5 版或更高版本的 ODBC 驱动程序 // 以同时支持 Unicode 和这些转换)。 // 重写 // 向导生成的虚函数重写 public: virtual CString GetDefaultConnect(); // 默认连接字符串 virtual CString GetDefaultSQL(); // 记录集的默认 SQL virtual void DoFieldExchange(CFieldExchange* pFX); // RFX 支持 // 实现 #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif };
sample2.cpp
} ///////////////////////////////////////////////////////////////////////////// // CXXXXXXXX Õï¶Ï #ifdef _DEBUG void CXXXXXXXX::AssertValid() const { CRecordset::AssertValid(); } void CXXXXXXXX::Dump(CDumpContext& dc) const { CRecordset::Dump(dc); } #endif //_DEBUG
相关文章推荐
- spread连接mysql,中文列名无法绑定的问题解决
- Java/JSP程序连接不上Mysql驱动问题解决方法
- sql server 2000下的关于“provider: TCP 提供程序, error: 0 - 远程主机强迫关闭了一个现有的连接”问题的解决
- 关于codeblocks连接mysql的问题解决
- 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题
- Java程序连接数据库(mysql,sql server)以及出现的问题解决
- 关于spring boot整合druid连接池在程序关闭后连接不释放问题解决
- 没有网络连接时程序崩溃问题以及动态加载图片问题已解决
- #菜鸟新手EclipseJavaEE&MySQL&Tomcat#关于一个Eclipse中登陆界面通过连接MySQL数据库进行验证的小体验(感谢qq群友引燃的解答让我解决这个小问题)
- 解决(Oracle)ORA-12528: TNS: 监听程序: 所有适用例程都无法建立新连接 问题
- 关于数据库连接出错问题的解决方法(mysql、postgresql)
- 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题
- 关于tomcat上运行mysql时间过长未连接引发的wait_time问题解决
- 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题
- 解决数据库连接池连接mysql时,每隔8小时mysql自动断开所有连接的问题
- 关于mysql_fetc_array()在左连接时被覆盖问题的解决
- 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。
- 关于mysql_query导致连接断开的问题
- 解决 c3p0 和 MySQL 集成情况下,连接长时间闲置后重新使用时报错的问题
- 关于MySQL的wait_timeout连接超时问题报错解决方案