C++/CLR写的Data Blocks
简介:
从Microsoft Enterprise Library 5.0 Data Blocks剥离出的数据库操作方法,重新用C++/clr语言封装的一个模块!
只实现几个简单常用的接口,用于c++/clr项目中。
写在代码前面:
项目是c++/clr的,所以他只需要c++/clr的代码,他不需要我提供dll方式的功能模块,他只需要.h和.cpp文件;
不想说了,其他事情还是放在心里吧,直接贴代码就好了!
项目结构:
实现的接口:
代码片段:
DataBase.h
public ref class DataBase
{
public:
DataBase(String ^connectionString,DbProviderFactory ^dbProviderFactory)
{
if(String::IsNullOrEmpty(connectionString))
throw gcnew ArgumentException("连接字符串不允许为空");
if (dbProviderFactory == nullptr)
throw gcnew ArgumentNullException("数据库提供类型不允许为空");
this->m_connectionString=connectionString;
this->m_dbProviderFactory=dbProviderFactory;
}
//连接字符串
property String ^ConnectionString
{
String ^get(){return m_connectionString;}
}
virtual int ExecuteNonQuery(DbCommand ^command);
virtual int ExecuteNonQuery(CommandType commandType,String ^commandText);
virtual Object ^ExecuteScalar(DbCommand ^command);
virtual Object ^ExecuteScalar(CommandType commandType,String ^commandText);
virtual DataSet ^ExecuteDataSet(DbCommand ^command);
virtual DataSet ^ExecuteDataSet(CommandType commandType,String ^commandText);
virtual IDataReader ^ExecuteReader(DbCommand ^command);
virtual IDataReader ^ExecuteReader(CommandType commandType,String ^commandText);
enum class UpdateBehavior
{
/// <summary>
/// No interference with the DataAdapter's Update command. If Update encounters
/// an error, the update stops. Additional rows in the Datatable are uneffected.
/// </summary>
Standard,
/// <summary>
/// If the DataAdapter's Update command encounters an error, the update will
/// continue. The Update command will try to update the remaining rows.
/// </summary>
Continue,
/// <summary>
/// If the DataAdapter encounters an error, all updated rows will be rolled back.
/// </summary>
Transactional
};
private:
String ^m_connectionString;
DbProviderFactory ^m_dbProviderFactory;
DbConnection ^GetNewOpenConnection();
DbCommand ^CreateCommandByCommandType(CommandType commandType,String ^commandText);
protected:
virtual DatabaseConnectionWrapper ^GetWrappedConnection();
static void PrepareCommand(DbCommand ^command,DbConnection ^connection);
int DoExecuteNonQuery(DbCommand ^command);
Object ^DoExecuteScalar(IDbCommand ^command);
IDataReader ^DoExecuteReader(DbCommand ^command,CommandBehavior cmdBehavior);
void DoLoadDataSet(DbCommand ^command,DataSet ^dataSet,array<String^> ^tableNames);
DbDataAdapter ^GetDataAdapter(UpdateBehavior updateBehavior);
virtual void SetUpRowUpdatedEvent(DbDataAdapter ^adapter) { }
};
{
public:
DataBase(String ^connectionString,DbProviderFactory ^dbProviderFactory)
{
if(String::IsNullOrEmpty(connectionString))
throw gcnew ArgumentException("连接字符串不允许为空");
if (dbProviderFactory == nullptr)
throw gcnew ArgumentNullException("数据库提供类型不允许为空");
this->m_connectionString=connectionString;
this->m_dbProviderFactory=dbProviderFactory;
}
//连接字符串
property String ^ConnectionString
{
String ^get(){return m_connectionString;}
}
virtual int ExecuteNonQuery(DbCommand ^command);
virtual int ExecuteNonQuery(CommandType commandType,String ^commandText);
virtual Object ^ExecuteScalar(DbCommand ^command);
virtual Object ^ExecuteScalar(CommandType commandType,String ^commandText);
virtual DataSet ^ExecuteDataSet(DbCommand ^command);
virtual DataSet ^ExecuteDataSet(CommandType commandType,String ^commandText);
virtual IDataReader ^ExecuteReader(DbCommand ^command);
virtual IDataReader ^ExecuteReader(CommandType commandType,String ^commandText);
enum class UpdateBehavior
{
/// <summary>
/// No interference with the DataAdapter's Update command. If Update encounters
/// an error, the update stops. Additional rows in the Datatable are uneffected.
/// </summary>
Standard,
/// <summary>
/// If the DataAdapter's Update command encounters an error, the update will
/// continue. The Update command will try to update the remaining rows.
/// </summary>
Continue,
/// <summary>
/// If the DataAdapter encounters an error, all updated rows will be rolled back.
/// </summary>
Transactional
};
private:
String ^m_connectionString;
DbProviderFactory ^m_dbProviderFactory;
DbConnection ^GetNewOpenConnection();
DbCommand ^CreateCommandByCommandType(CommandType commandType,String ^commandText);
protected:
virtual DatabaseConnectionWrapper ^GetWrappedConnection();
static void PrepareCommand(DbCommand ^command,DbConnection ^connection);
int DoExecuteNonQuery(DbCommand ^command);
Object ^DoExecuteScalar(IDbCommand ^command);
IDataReader ^DoExecuteReader(DbCommand ^command,CommandBehavior cmdBehavior);
void DoLoadDataSet(DbCommand ^command,DataSet ^dataSet,array<String^> ^tableNames);
DbDataAdapter ^GetDataAdapter(UpdateBehavior updateBehavior);
virtual void SetUpRowUpdatedEvent(DbDataAdapter ^adapter) { }
};
DataBase.cpp
#include "DataBase.h"
using namespace DBManager;
/*返回数据库语句执行所影响的行数:int*/
int DataBase::ExecuteNonQuery(DbCommand ^command)
{
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
int ret=DoExecuteNonQuery(command);
delete command;
delete wrapper;
return ret;
}
int DataBase::ExecuteNonQuery(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteNonQuery(command);
}
int DataBase::DoExecuteNonQuery(DbCommand ^command)
{
try{
int rowsAffected = command->ExecuteNonQuery();
return rowsAffected;
}
catch(Exception ^e)
{
throw e;
}
}
/*返回数据库语句执行结果:Object*/
Object ^DataBase::ExecuteScalar(DbCommand ^command)
{
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
Object ^ret=DoExecuteScalar(command);
delete command;
delete wrapper;
return ret;
}
Object ^DataBase::ExecuteScalar(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteScalar(command);
}
Object ^DataBase::DoExecuteScalar(IDbCommand ^command)
{
try{
Object ^returnValue = command->ExecuteScalar();
return returnValue;
}
catch(Exception ^e)
{
throw e;
}
}
/*返回数据库语句执行结果:DataSet*/
DataSet ^DataBase::ExecuteDataSet(DbCommand ^command)
{
DataSet ^dataSet = gcnew DataSet();
dataSet->Locale = System::Globalization::CultureInfo::InvariantCulture; //获取不依赖于区域性(固定)的 CultureInfo。
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
DoLoadDataSet(command, dataSet, gcnew array<String^>{"Table"});
delete wrapper;
return dataSet;
}
DataSet ^DataBase::ExecuteDataSet(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteDataSet(command);
}
void DataBase::DoLoadDataSet(DbCommand ^command,DataSet ^dataSet,array<String^> ^tableNames)
{
if (tableNames == nullptr)
throw gcnew ArgumentNullException("表名数组不允许为空");
if (tableNames->Length == 0)
{
throw gcnew ArgumentException("表名数组长度为0");
}
for (int i = 0; i < tableNames->Length; i++)
{
if (String::IsNullOrEmpty(tableNames[i]))
throw gcnew ArgumentException(String::Concat("表名数组第[", i, "]项为空"));
}
DbDataAdapter ^adapter = GetDataAdapter(UpdateBehavior::Standard);
((IDbDataAdapter^)adapter)->SelectCommand = command;
try
{
String ^systemCreatedTableNameRoot = "Table";
for (int i = 0; i < tableNames->Length; i++)
{
String ^systemCreatedTableName = (i == 0)
? systemCreatedTableNameRoot
: systemCreatedTableNameRoot + i; //Table,Table1,Table2
adapter->TableMappings->Add(systemCreatedTableName, tableNames[i]);
}
adapter->Fill(dataSet);
}
catch(Exception ^e)
{
throw e;
}
finally
{
delete adapter;
}
}
DbDataAdapter ^DataBase::GetDataAdapter(UpdateBehavior updateBehavior)
{
DbDataAdapter ^adapter = m_dbProviderFactory->CreateDataAdapter();
if (updateBehavior == UpdateBehavior::Continue)
{
SetUpRowUpdatedEvent(adapter); //define in ".h"
}
return adapter;
}
/*返回数据库语句执行结果:DataReader*/
IDataReader ^DataBase::ExecuteReader(DbCommand ^command)
{
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
IDataReader ^realReader = DoExecuteReader(command, CommandBehavior::Default);
RefCountingDataReader ^reader=gcnew RefCountingDataReader(wrapper, realReader);
return reader->InnerReader;
}
IDataReader ^DataBase::ExecuteReader(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteReader(command);
}
IDataReader ^DataBase::DoExecuteReader(DbCommand ^command,CommandBehavior cmdBehavior)
{
try{
IDataReader ^reader = command->ExecuteReader(cmdBehavior);
return reader;
}
catch(Exception ^e)
{
throw e;
}
}
/*添加DbCommand对象的DbConnection属性*/
void DataBase::PrepareCommand(DbCommand ^command,DbConnection ^connection)
{
if (command == nullptr) throw gcnew ArgumentNullException("不允许空的DbCommand对象");
if (connection == nullptr) throw gcnew ArgumentNullException("不允许空的DbConnection对象");
command->Connection=connection;
}
/*返回一个DatabaseConnectionWrapper对象*/
DatabaseConnectionWrapper ^DataBase::GetWrappedConnection()
{
return gcnew DatabaseConnectionWrapper(GetNewOpenConnection());
}
/*返回数据库连接对象:DbConnection*/
DbConnection ^DataBase::GetNewOpenConnection()
{
DbConnection ^connection=nullptr;
try
{
try
{
connection=m_dbProviderFactory->CreateConnection();
connection->ConnectionString=m_connectionString;
connection->Open();
}
catch(Exception ^ex)
{
throw ex;
}
}
catch(Exception ^e)
{
if(connection!=nullptr)
connection->Close();
throw e;
}
return connection;
}
/*返回一个DbCommand对象*/
DbCommand ^DataBase::CreateCommandByCommandType(CommandType commandType,String ^commandText)
{
DbCommand ^command = m_dbProviderFactory->CreateCommand();
command->CommandType = commandType;
command->CommandText = commandText;
return command;
}
#include "DataBase.h"
using namespace DBManager;
/*返回数据库语句执行所影响的行数:int*/
int DataBase::ExecuteNonQuery(DbCommand ^command)
{
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
int ret=DoExecuteNonQuery(command);
delete command;
delete wrapper;
return ret;
}
int DataBase::ExecuteNonQuery(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteNonQuery(command);
}
int DataBase::DoExecuteNonQuery(DbCommand ^command)
{
try{
int rowsAffected = command->ExecuteNonQuery();
return rowsAffected;
}
catch(Exception ^e)
{
throw e;
}
}
/*返回数据库语句执行结果:Object*/
Object ^DataBase::ExecuteScalar(DbCommand ^command)
{
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
Object ^ret=DoExecuteScalar(command);
delete command;
delete wrapper;
return ret;
}
Object ^DataBase::ExecuteScalar(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteScalar(command);
}
Object ^DataBase::DoExecuteScalar(IDbCommand ^command)
{
try{
Object ^returnValue = command->ExecuteScalar();
return returnValue;
}
catch(Exception ^e)
{
throw e;
}
}
/*返回数据库语句执行结果:DataSet*/
DataSet ^DataBase::ExecuteDataSet(DbCommand ^command)
{
DataSet ^dataSet = gcnew DataSet();
dataSet->Locale = System::Globalization::CultureInfo::InvariantCulture; //获取不依赖于区域性(固定)的 CultureInfo。
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
DoLoadDataSet(command, dataSet, gcnew array<String^>{"Table"});
delete wrapper;
return dataSet;
}
DataSet ^DataBase::ExecuteDataSet(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteDataSet(command);
}
void DataBase::DoLoadDataSet(DbCommand ^command,DataSet ^dataSet,array<String^> ^tableNames)
{
if (tableNames == nullptr)
throw gcnew ArgumentNullException("表名数组不允许为空");
if (tableNames->Length == 0)
{
throw gcnew ArgumentException("表名数组长度为0");
}
for (int i = 0; i < tableNames->Length; i++)
{
if (String::IsNullOrEmpty(tableNames[i]))
throw gcnew ArgumentException(String::Concat("表名数组第[", i, "]项为空"));
}
DbDataAdapter ^adapter = GetDataAdapter(UpdateBehavior::Standard);
((IDbDataAdapter^)adapter)->SelectCommand = command;
try
{
String ^systemCreatedTableNameRoot = "Table";
for (int i = 0; i < tableNames->Length; i++)
{
String ^systemCreatedTableName = (i == 0)
? systemCreatedTableNameRoot
: systemCreatedTableNameRoot + i; //Table,Table1,Table2
adapter->TableMappings->Add(systemCreatedTableName, tableNames[i]);
}
adapter->Fill(dataSet);
}
catch(Exception ^e)
{
throw e;
}
finally
{
delete adapter;
}
}
DbDataAdapter ^DataBase::GetDataAdapter(UpdateBehavior updateBehavior)
{
DbDataAdapter ^adapter = m_dbProviderFactory->CreateDataAdapter();
if (updateBehavior == UpdateBehavior::Continue)
{
SetUpRowUpdatedEvent(adapter); //define in ".h"
}
return adapter;
}
/*返回数据库语句执行结果:DataReader*/
IDataReader ^DataBase::ExecuteReader(DbCommand ^command)
{
DatabaseConnectionWrapper ^wrapper=GetWrappedConnection();
PrepareCommand(command,wrapper->Connection);
IDataReader ^realReader = DoExecuteReader(command, CommandBehavior::Default);
RefCountingDataReader ^reader=gcnew RefCountingDataReader(wrapper, realReader);
return reader->InnerReader;
}
IDataReader ^DataBase::ExecuteReader(CommandType commandType,String ^commandText)
{
DbCommand ^command = CreateCommandByCommandType(commandType, commandText);
return ExecuteReader(command);
}
IDataReader ^DataBase::DoExecuteReader(DbCommand ^command,CommandBehavior cmdBehavior)
{
try{
IDataReader ^reader = command->ExecuteReader(cmdBehavior);
return reader;
}
catch(Exception ^e)
{
throw e;
}
}
/*添加DbCommand对象的DbConnection属性*/
void DataBase::PrepareCommand(DbCommand ^command,DbConnection ^connection)
{
if (command == nullptr) throw gcnew ArgumentNullException("不允许空的DbCommand对象");
if (connection == nullptr) throw gcnew ArgumentNullException("不允许空的DbConnection对象");
command->Connection=connection;
}
/*返回一个DatabaseConnectionWrapper对象*/
DatabaseConnectionWrapper ^DataBase::GetWrappedConnection()
{
return gcnew DatabaseConnectionWrapper(GetNewOpenConnection());
}
/*返回数据库连接对象:DbConnection*/
DbConnection ^DataBase::GetNewOpenConnection()
{
DbConnection ^connection=nullptr;
try
{
try
{
connection=m_dbProviderFactory->CreateConnection();
connection->ConnectionString=m_connectionString;
connection->Open();
}
catch(Exception ^ex)
{
throw ex;
}
}
catch(Exception ^e)
{
if(connection!=nullptr)
connection->Close();
throw e;
}
return connection;
}
/*返回一个DbCommand对象*/
DbCommand ^DataBase::CreateCommandByCommandType(CommandType commandType,String ^commandText)
{
DbCommand ^command = m_dbProviderFactory->CreateCommand();
command->CommandType = commandType;
command->CommandText = commandText;
return command;
}
测试代码
void CallBack(Object ^obj)
{
//Sql Server数据库测试
String ^strConn="Data Source=localhost,8306;Initial Catalog=SensorLeadDB;User ID=sa;Password=HZ.bridge";
SqlDataBase ^sqlbase=gcnew SqlDataBase(strConn);
int m_count=sqlbase->SqlExecuteNonQuery("delete from OriginalDatas where SendTime>'2010-06-15' and Sensorid='1-1-2'");
Object ^m_obj=sqlbase->SqlExecuteScalar("select Sensorid from Sensor");
DataSet ^m_set=sqlbase->SqlExecuteDataSet("select * from Sensor");
SqlDataReader ^m_reader=sqlbase->SqlExecuteReader("select Sensorid,SensorType from Sensor");
Console::WriteLine("Delete Result:{0}",m_count);
Console::WriteLine("Select Result:{0}",m_obj);
int tablesCount=m_set->Tables->Count;
for (int i=0;i<tablesCount;i++)
{
Console::WriteLine("DataSet Result:TableName ={0},RowCount={1}",m_set->Tables[i]->TableName,m_set->Tables[i]->Rows->Count);
}
Console::WriteLine("SqlDataReader Result:HasRows={0}",m_reader->HasRows);
//Access数据库测试
strConn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=mydatabase.mdb;";
GenericDatabase ^gdb=gcnew GenericDatabase(strConn,OleDbFactory::Instance);
m_count=gdb->ExecuteNonQuery(CommandType::Text,"insert into userinfo(name,pass) values('test','123456')");
m_obj=gdb->ExecuteScalar(CommandType::Text,"select count(*) from userinfo");
Console::WriteLine("Delete Result:{0}",m_count);
Console::WriteLine("Select Result:{0}",m_obj);
frmShow ^frm=gcnew frmShow(m_set,m_reader);
frm->ShowDialog();
}
int main(array<System::String ^> ^args)
{
WaitCallback ^call=gcnew WaitCallback(CallBack);
for (int i=0;i<3;i++)
{
ThreadPool::QueueUserWorkItem(call); //并发测试
}
Console::ReadLine();
return 0;
}
{
//Sql Server数据库测试
String ^strConn="Data Source=localhost,8306;Initial Catalog=SensorLeadDB;User ID=sa;Password=HZ.bridge";
SqlDataBase ^sqlbase=gcnew SqlDataBase(strConn);
int m_count=sqlbase->SqlExecuteNonQuery("delete from OriginalDatas where SendTime>'2010-06-15' and Sensorid='1-1-2'");
Object ^m_obj=sqlbase->SqlExecuteScalar("select Sensorid from Sensor");
DataSet ^m_set=sqlbase->SqlExecuteDataSet("select * from Sensor");
SqlDataReader ^m_reader=sqlbase->SqlExecuteReader("select Sensorid,SensorType from Sensor");
Console::WriteLine("Delete Result:{0}",m_count);
Console::WriteLine("Select Result:{0}",m_obj);
int tablesCount=m_set->Tables->Count;
for (int i=0;i<tablesCount;i++)
{
Console::WriteLine("DataSet Result:TableName ={0},RowCount={1}",m_set->Tables[i]->TableName,m_set->Tables[i]->Rows->Count);
}
Console::WriteLine("SqlDataReader Result:HasRows={0}",m_reader->HasRows);
//Access数据库测试
strConn="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=mydatabase.mdb;";
GenericDatabase ^gdb=gcnew GenericDatabase(strConn,OleDbFactory::Instance);
m_count=gdb->ExecuteNonQuery(CommandType::Text,"insert into userinfo(name,pass) values('test','123456')");
m_obj=gdb->ExecuteScalar(CommandType::Text,"select count(*) from userinfo");
Console::WriteLine("Delete Result:{0}",m_count);
Console::WriteLine("Select Result:{0}",m_obj);
frmShow ^frm=gcnew frmShow(m_set,m_reader);
frm->ShowDialog();
}
int main(array<System::String ^> ^args)
{
WaitCallback ^call=gcnew WaitCallback(CallBack);
for (int i=0;i<3;i++)
{
ThreadPool::QueueUserWorkItem(call); //并发测试
}
Console::ReadLine();
return 0;
}
项目文件下载: /Files/cxwx/DBManager.rar
文件DatabaseConnectionWrapper中如下部分稍作修改
//Dispose
~DatabaseConnectionWrapper()
{
int count = Interlocked::Decrement(refCount); //以原子操作的形式递减指定变量的值并存储结果 返回0 refCount=1
if (count == 0)
{
m_Connection->~DbConnection();
}
}
!DatabaseConnectionWrapper()
{
//...
}