2014-09-12 43 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

相关问题