c# 與 Mysql 的通訊方式總結


兩種開發方式

1.使用 vs 自帶的可視化工具,不推薦。

在 vs 的項目中添加 ‘數據集’,然后通過可視化的工具添加數據庫為數據源,默認可添加 SQL Server 和 Oracle 等,添加 Mysql 前需要額外安裝組件。

優點,自帶 sql 語句中特殊字符的轉義,不會出現 sql 注入的問題,配合數據綁定可以在項目前期快速推進項目進度。

缺點:可視化工具的使用並不流行,不利於開發團隊的招募和項目后期的修改維護。許多常用的功能很難使用,如:存儲過程,事務,連接池控制等。

2.引用 mysql.data.dll ,在此基礎上進行開發,推薦。

完全由代碼完成通訊過程。

優點:可以方便的使用各種功能,

缺點:需要手寫代碼,開發速度稍慢。


 


 

完整的通訊過程

1.建立連接,連接分 “長連接” 和 “短連接” 

長連接在高頻次的通訊時快速高效,但是占用資源,在並發訪問下容易耗盡網絡資源,對於帶寬較低的局域網來說,如果大量使用長連接,會占用網速,影響使用體驗。

短連接在使用時 open, 使用完成后 close,此時連接資源會進入連接池,等待下次連接時使用。雖然資源未被釋放掉,但連接池的開銷不大,是完全可以接受的。短連接一樣需要考慮並發問題。

短連接在使用完成后可以直接 dispose,或者使用 using(){} 來限定連接的作用域,使用完成后自動釋放掉,不進入連接池,這種方式資源占用最少,但在需要反復建立連接的情況下連接效率較低。

在實際開發的時候最好使用短連接,並在使用結束后關閉並放入連接池。

string connStr = "server=127.0.0.1; port=3306; user id=user1; Password=pass1; database=data1; pooling = true";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open(); 
conn.Close();

2.使用連接創建 sql 命令並執行

1.純 sql 語句,執行后有三種返回方式:

cmd.ExecuteScalar();  // 查詢結果僅一行一列,直接接收

string connStr = "server=127.0.0.1; port=3306; user id=user1; Password=pass1; database=data1; pooling = true";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
MySqlCommand cmd = conn.CreateCommand();
string name = "Tom";
cmd.CommandText = string.Format("select  count(*) from student where Name = '{0}';", name);
object obj = cmd.ExecuteScalar(); //可能未null
int count = 0;
if (!obj.Equals(DBNull.Value))
{
  count = Convert.ToInt32(obj);
}
conn.Close();

 

 

MySqlDataReader reader = cmd.ExecuteReader();  // 通過 reader 獲得大量數據

string connStr = "server=127.0.0.1; port=3306; user id=user1; Password=pass1; database=data1; pooling = true";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = string.Format("select  Name from student;");
MySqlDataReader reader = cmd.ExecuteReader();
List<string> list = new List<string>();
while (reader.Read())
{
    list.Add(reader.GetString("Name"));
}
reader.Close();
conn.Close();

 

cmd.ExecuteNonQuery();  // 獲得增刪改語句執行后影響的行數

string connStr = "server=127.0.0.1; port=3306; user id=user1; Password=pass1; database=data1; pooling = true";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
MySqlCommand cmd = conn.CreateCommand();
string name = "Tom";
cmd.CommandText = string.Format("update student SET Name='Tommy' where Name = '{0}';", name);
int count = cmd.ExecuteNonQuery();
conn.Close();

 

普通 sql 語句的缺點:如果上面例子中的 name 參數中帶有單引號,整個 sql 語句將執行錯誤,因為未對特殊字符進行轉義。主要特殊字符有單引號,反斜杠,# 等,而這些特殊字符在不同的使用情況下有時需要轉義,有時不需要轉義。Mysql 提供了類似 QUOTE(str) 這樣的字符串處理函數,但不能完全滿足要求。

這就是 sql 注入,sql 注入的概念網上資料較多,在此不再贅述,而常用的解決方案是采用參數化的 sql 語句。

2.sql 語句和 sql 參數

帶有參數的 sql 語句和 sql 參數會分開傳入數據庫服務器中,服務器先將 sql 語句進行編譯,然后將 sql 參數導入編譯后的 sql 語句中(在此過程中自動對特殊字符進行轉義),從而從根源上防止了 sql 注入的發生。

string connStr = "server=127.0.0.1; port=3306; user id=user1; Password=pass1; database=data1; pooling = true";
MySqlConnection conn = new MySqlConnection(connStr);
conn.Open();
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select  count(*) from student where Name = @Name;";
cmd.Parameters.AddWithValue("@Name", "Tom");
object obj = cmd.ExecuteScalar(); //可能為null int count = 0; if (!obj.Equals(DBNull.Value)) { count = Convert.ToInt32(obj); } conn.Close(); 

3.DataAdapter

 private static void Test(MySqlCommand cmd)
        {
            //獲取記錄
            DataTable dt1 = new DataTable();
            cmd.CommandText = "select * from table1;";
            MySqlDataAdapter da = new MySqlDataAdapter(cmd);
            da.Fill(dt1);


            //插入記錄
            cmd.CommandText = "select * from pet where 1=0;";
            da = new MySqlDataAdapter(cmd);
            MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
            da.UpdateCommand = cb.GetInsertCommand();
            DataTable dt2 = new DataTable();
            da.Fill(dt2);
            //對dt2進行賦值
            da.Update(dt2);
        }

4.事務

多條 sql 語句的組合會出現某一條 sql 語句執行出錯,而其他 sql 語句順利執行的情況,這可能與預期不符合。此時需要使用事務。

事務在執行出錯時可以回滾。

事務往往帶有多條 sql 語句,在使用參數化的 sql 語句時要注意參數名稱不能相同。

conn.Open();
MySqlCommand cmd = conn.CreateCommand();
MySqlTransaction myTrans = conn.BeginTransaction();
cmd.Connection = conn;
cmd.Transaction = myTrans;
cmd.CommandText = "";
cmd.ExecuteNonQuery();
myTrans.Commit();
conn.Close();

5.存儲過程

不論是 sql 語句還是事務,在傳輸指令的時候都需要耗費大量的時間,數據庫編譯這些指令也需要耗費大量時間,這不利於高訪問量的數據庫的運行。

存儲過程是將 sql 指令寫在數據庫中,此時數據庫直接完成編譯,與數據庫通訊是只需要傳遞參數即可。節省了傳輸時間和編譯時間。

conn.Open();
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SpFillStudent";

MySqlParameter paraMoney;
paraMoney = cmd.Parameters.Add("@inMoney", MySqlDbType.Decimal);
paraMoney.Direction = ParameterDirection.Input;
paraMoney.Value = 50;

MySqlParameter paraTradeType;
paraTradeType = cmd.Parameters.Add("@inTradeType", MySqlDbType.String);
paraTradeType.Direction = ParameterDirection.Input;
paraTradeType.Value = "會員卡充值";

MySqlParameter paraPayDetailStr;
paraPayDetailStr = cmd.Parameters.Add("@inPayDetailStr", MySqlDbType.String);
paraPayDetailStr.Direction = ParameterDirection.Input;
paraPayDetailStr.Value = "";

MySqlParameter paraOutResult;
paraOutResult = cmd.Parameters.Add("@outResult", MySqlDbType.String);
paraOutResult.Direction = ParameterDirection.Output;

cmd.ExecuteNonQuery();
string result = (string)paraOutResult.Value;
conn.Close();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM