.net app中的不同数据库类型

时间:2014-09-12 16:20:55

标签: c# .net

我正在用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等为三种数据库类型重复上述所有内容的最佳方法?

非常感谢您的任何帮助。

乔恩

1 个答案:

答案 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等之间交换,请创建相应的处理程序。