ADO .NET總結
ADO .NET主要用到了:
- SqlConnection-連線資料庫
- SqlCommand-執行SQL語句或者儲存過程
- SqlDataReader-執行SQL語句後資料儲存於該資料流中
- SqlDataAdapter-將資料儲存在DataSet中
外加幾個涉及到安全的類:
- SqlConnectionStringBuilder-生成連線字串
- SqlParameter-用引數的形式組裝SQL語句
具體可以查閱MSDN ADO相關頁面,下面是例項:
首先建立一個測試資料庫:
create database students use students create table stu( id int, name varchar(10), sex char(2) ) insert into stu(id, name, sex) values(1,'小明','女')
1.連線資料庫
SqlConnection用來連線資料庫,這是一切的開始,主要用到兩個方法
- Open()連線資料庫
- Close()關閉資料庫連線,這是必須的。
建立一個c#控制檯程式,例項程式碼都會在這裡面完成
引入名稱空間
using System.Data.SqlClient;
連線資料庫需要連線字串,連線SQL Server的字串一般格式為
- Data Source=計算機名或者IP地址;Initial Catalog=資料庫名;User ID=登入ID;Password=密碼;
在控制檯程式中新增一個連線資料庫的方法,並在Main中呼叫
static void Main(string[] args) { conDataBase(); Console.Read(); } public static void conDataBase() { using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;")) { try { con.Open(); Console.Write("資料庫連線成功!"); } catch { Console.Write("資料庫連線失敗!"); } } }
利用using語句可以自動釋放相關資源,如果不使用using需要con.Close()方法關閉連線。執行結果:
這樣就成功連線到了資料庫,下面便是對資料庫執行操作。
2.SqlCommand && DataReader
SqlCommand一般用到下面幾個方法:
命令 | 返回值 |
---|---|
ExecuteReader |
執行查詢,返回一個 DataReader 物件。 |
ExecuteScalar |
執行查詢,並返回由查詢返回的結果集中的第一行的第一列,其他列或行將被忽略。 |
ExecuteNonQuery |
一般執行增刪改語句,返回受影響行數 |
一般用到的屬性有:
Connection | 獲取或設定 SqlCommand 的此例項使用的 SqlConnection。 |
CommandText | 獲取或設定要在資料來源中執行的 Transact-SQL 語句、表名或儲存過程。 |
可以直接用相關建構函式去宣告一個SqlCommand類,省去了設定上面兩個屬性:SqlCommand("SQL語句","SqlConnection物件");
DataReader是一個只能讀取且只能前進的資料流,用read()方法讀取下一個資料。不能直接建立一個DataReader物件,必須通過SqlCommand的ExecuteReader方法來構建一個DataReader物件。最後也必須使用Close()關閉Reader流。
ExecuteReader例項:
新增一個方法,並在Main中呼叫:
public static void DataReader()
{
using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;"))
{
try
{
SqlCommand com = new SqlCommand("select * from stu", con);
con.Open();
SqlDataReader read = com.ExecuteReader();
while(read.Read())
{
Console.WriteLine(read["id"].ToString() + " - " + read["name"].ToString()+ " - " + read["sex"].ToString());
}
}
catch (Exception ex)
{
Console.Write(ex);
}
}
}
執行結果:
ExecuteNonQuery例項:
public static void UpDateDateBase()
{
using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;"))
{
try
{
con.Open();
//插入一條資料
SqlCommand com = new SqlCommand("insert into stu(id, name, sex) values(2,'小紅','男')", con);
int i = com.ExecuteNonQuery();
Console.WriteLine("更新了{0}條資料",i);
//列印目前的資料
com.CommandText = "select * from stu";
SqlDataReader read = com.ExecuteReader();
while(read.Read())
{
Console.WriteLine(read["id"].ToString() + " - " + read["name"].ToString() + " - " + read["sex"].ToString());
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
執行結果:
ExecuteScalar 例項:
ExecuteScalat方法返回單個值,該值是一個Object型別,需要進行轉換
public static void DataScalar()
{
using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;"))
{
try
{
SqlCommand com = new SqlCommand("select name from stu where id = 1", con);
con.Open();
string name = com.ExecuteScalar().ToString();
Console.Write(name);
}
catch (Exception ex)
{
Console.Write(ex);
}
}
}
執行結果:
3.SqlParameter
上面的例項中都是直接寫死了一個SQL查詢語句,實際上並不會這樣用,都是接受引數去組成SQL語句的Where部分,可能有的人直接用拼接字串的方法來組成SQL語句,不過這樣做會有風險,舉個例子:
public static void DataReader(string id)
{
using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;"))
{
try
{
SqlCommand com = new SqlCommand("select * from stu where id = " + id, con);
con.Open();
SqlDataReader read = com.ExecuteReader();
while(read.Read())
{
Console.WriteLine(read["id"].ToString() + " - " + read["name"].ToString()+ " - " + read["sex"].ToString());
}
}
catch (Exception ex)
{
Console.Write(ex);
}
}
}
將上面的例子改為接收一個id引數去查詢資料庫,當引數是正常填入,比如1,這個方法沒有任何問題,輸出:這也是我們想要的效果,不過如果在引數上動點手腳,情況就不一樣了,將傳入的引數改為:
DataReader("'' or 1 = 1");
執行結果:這下子我們的資料全部暴露出來了,這種方式就是SQL注入。
可疑利用SqlParameter避免這種情況,用SqlParameter改造上面的例子:
public static void DataReader(string id)
{
using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;"))
{
try
{
SqlCommand com = new SqlCommand("select * from stu where id = @id", con);
SqlParameter _id = new SqlParameter("@id",id);
com.Parameters.Add(_id);
/*也可以寫成
com.Parameters.Add(new SqlParameter("@id", id));
*/
con.Open();
SqlDataReader read = com.ExecuteReader();
while(read.Read())
{
Console.WriteLine(read["id"].ToString() + " - " + read["name"].ToString()+ " - " + read["sex"].ToString());
}
}
catch (Exception ex)
{
Console.Write(ex);
}
}
}
這個時候引數輸入'' or 1 = 1就會發生錯誤,從而避免了被注入攻擊。
當有多個引數的時候,可以寫多個com.Parameters.Add()方法或者建立Parameters陣列與AddRange()方法,例:
SqlParameter[] parameter = new SqlParameter[]
{
new SqlParameter("@id", id),
new SqlParameter("@name", "小明")
};
com.Parameters.AddRange(parameter);
4.SqlDataAdapter && DataSet
SqlDataAdapter主要用來將資料填充到DataSet中
主要屬性有:
SelectCommand | 獲取或設定一個 TRANSACT-SQL 語句或儲存的過程用於在資料來源中選擇記錄。 |
主要方法有:
Fill(DataSet) | 在 DataSet 中新增或重新整理行。 (Inherited from DbDataAdapter) |
DataSet並不單單用於儲存資料庫中查詢出來的資料,不過這裡並不討論其它情況,就只說資料庫的內容。
程式碼奉上:
public static void DataSet()
{
using (SqlConnection con = new SqlConnection("Data Source=你的電腦名;Initial Catalog=students;User ID=你的ID;Password=你的密碼;"))
{
try
{
con.Open();
SqlCommand com = new SqlCommand("select * from stu", con);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = com;
DataSet ds = new DataSet();
da.Fill(ds);
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
Console.WriteLine(ds.Tables[0].Rows[i]["id"].ToString() + " - " + ds.Tables[0].Rows[i]["name"].ToString() + " - " + ds.Tables[0].Rows[i]["sex"].ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
最後可以將上面的幾個方法整理一下,使其成為一個類庫,就可以較為方便地操作資料庫。