2014-09-12 72 views
-2

我正在C#中編寫一個需要連接到三種不同類型數據庫(SQL Server,MySQL或SQL Server Compact)之一的「現成」桌面應用程序,具體取決於版本和客戶要求。.net應用程序中的不同數據庫類型

我一直在使用ADO代碼如下:

using (SqlConnection conn = MSSQLHelpers.GetConnection()) 
{ 
    using (SqlCommand cmd = new SqlCommand()) 
    { 
     cmd.Connection = conn; 
     cmd.CommandType = CommandType.Text; 
     cmd.CommandText = "SELECT * FROM settings WHERE [email protected]"; 
     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

你看過文檔嗎?你會注意到SqlConnection和朋友是基於DbConnection和friends.Protip:使用Dapper.NET – leppie 2014-09-12 16:30:45

+0

http://msdn.microsoft.com/en-us/library/dd0w4a2z(v=vs.110).aspx – Mick 2014-09-12 17:04:42

+0

http ://blog-of-darius.blogspot.com.au/2011/07/c-idbconnection-idbcommand-idatareader.html – Mick 2014-09-12 17:10:51

回答

-1

其實我已經做過類似的,和我沒有使用接口層次結構類結構。例如,如果查看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等之間進行交換,請創建相應的處理程序。

+0

重新創造輪子。你不需要任何這些代碼,你可以使用內置的DbProviderFactory來實現所有這些,並堅持使用接口IDbConnection,IDbCommand – Mick 2014-09-12 17:10:10

+0

@Mick,是的,非常類似於DbProviderFactory,但額外用於處理中央不同的數據庫。 SQL命令使用不同的參數化命名約定「?」 vs「:」vs「@」等。我的版本雖然類似也包裝查詢連接等。 – DRapp 2014-09-12 17:25:02

+0

http://blog-of-darius.blogspot.com.au/2011/07/c-idbconnection-idbcommand-idatareader .html – Mick 2014-09-12 17:25:28

相關問題