我正在用C#编写一个“现成的”桌面应用程序,它需要连接到三种不同类型的数据库之一(SQL Server,MySQL或SQL Server Compact),具体取决于版本和客户要求。
我一直在使用ADO代码如下:
using (SqlConnection conn = MSSQLHelpers.GetConnection())
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM settings WHERE ID=@ID";
cmd.Parameters.AddWithValue("@ID", 1);
using (SqlDataReader rdr = MSSQLHelpers.GetDataReader(cmd))
{
if (rdr.Read())
{
Config.AdvancedSecurity = rdr.GetBoolean(rdr.GetOrdinal("advancedsecurity"));
Config.BookSampleInOnCreate = rdr.GetBoolean(rdr.GetOrdinal("newsamplein"));
etc....
}
rdr.Close();
}
}
conn.Close();
}
这显然是特定于SQL Server的。我的问题是什么是避免使用MySqlConnection,SqlCeConnection等为三种数据库类型重复上述所有内容的最佳方法?
非常感谢您的任何帮助。
乔恩
答案 0 :(得分:-1)
我实际上做过类似的事情,并且使用INTERFACES进行了层次结构类结构。例如,如果查看SqlConnection,则声明为包含“IDbConnection”接口。同样,SqlCommand包含“IDbCommand”,SqlDataAdapter使用“IDbDataAdapter”,类似参数等。
所以,我有一个类似于模板的父类(几乎都是一个抽象类),但由于我有一些常见的东西,无论哪种连接类型,它实际上也是一个函数类。
public class MyDBHandler
{
public virtual IDbConnection GetConnection()
{ throw new Exception( "Please define specific GetConnection method"}; }
public virtual IDbCommand GetCommand()
{ throw new Exception( "Please define specific GetCommand method"}; }
public virtual IDbDataAdapter GetDataAdapter()
{ throw new Exception( "Please define specific DataAdapter method"}; }
public virtual string GetConnectionString()
{ throw new Exception( "Please define specific ConnectionString method"}; }
etc...
// Then some common properties you might want for connection path, server, user, pwd
protected string whatServer;
protected string whatPath;
protected string whatUser;
protected string whatPwd;
protected connectionHandle;
public MyDBHandler()
{
// always start with HAVING a connection object, regardless of actual connection or not.
connectionHandle = GetConnection();
}
// common function to try opening corresponding connection regardless of which server type
public bool TryConnect()
{
if( connectionHandle.State != System.Data.ConnectionState.Open )
try
{
connectionHandle.ConnectionString = GetConnectionString();
connectionHandle.Open();
}
catch( Exception ex )
{
// notify user or other handling
}
if( connectionHandle.State != System.Data.ConnectionState.Open )
MessageBox.Show( "Some message to user." );
// return true only if state is open
return connectionHandle.State == System.Data.ConnectionState.Open;
}
// Now, similar to try executing a command as long as it is of IDbCommand interface to work with
public bool TryExec( IDbCommand whatCmd, DataTable putResultsHere )
{
// if can't connect, get out
if( ! TryConnect() )
return false;
bool sqlCallOk = false;
if( putResultsHere == null )
putResultsHere = new DataTable();
try
{
da.Fill(oTblResults, putResultsHere);
// we got this far without problem, it was ok, regardless of actually returning valid data
sqlCallOk = true;
}
catch( Exception ex )
{
// Notify user of error
}
return sqlCallOk;
}
}
public class SQLHandler : MyDbHandler
{
public override IDbConnection GetConnection()
{ return (IDbConnection) new SqlConnection(); }
public override IDbCommand GetCommand()
{ return (IDbCommand) new SqlCommand("", connectionHandle ); }
public override IDbDataAdapter GetDataAdapter()
{ return (IDbDataAdapter) new SqlDataAdapter(); }
public override string GetConnectionString()
{ return "Driver={SQL Server}; blah, blah of properties"; }
}
public class MySQLHandler : MyDbHandler
{
public override IDbConnection GetConnection()
{ return (IDbConnection) new MySqlConnection(); }
public override IDbCommand GetCommand()
{ return (IDbCommand) new MySqlCommand("", connectionHandle ); }
public override IDbDataAdapter GetDataAdapter()
{ return (IDbDataAdapter) new MySqlDataAdapter(); }
public override string GetConnectionString()
{ return "Driver={MySql}; blah, blah of properties"; }
}
然后,在您的代码中,根据您想要处理的方式,您可以
MyDbHandler whichDatabase = new SQLHandler();
// set any settings for such connection and such...
IDbCommand cmd = whichDatabase.GetCommand();
cmd.CommandText = "select * from whereEver";
DataTable oTmp = new DataTable()
whichDatabase.TryExec( cmd, oTmp );
现在您返回了一个表,并根据需要使用查询中的行/列填充,在TryExec()调用中关闭连接,或者您认为合适。
只是我过去所做过的精简版。
如果要在MySql,Sql-Server,Access,Visual FoxPro等之间交换,请创建相应的处理程序。