本文轉載自:http://www.youarebug.com/forum.php?mod=viewthread&tid=57&page=1&extra=#pid63 或者: 或者: 或者: 註:上面的代碼主要是數據集的展示功能,需要註意的是填充數據表的語句,是由DataSet對象的Tables屬性的
本文轉載自:http://www.youarebug.com/forum.php?mod=viewthread&tid=57&page=1&extra=#pid63
這是本人在學習ADP.NET過程中所作的筆記,可作為ADO.NET入門或者複習的教程。 連接字元串: DataSource=localhost; AttchDBFilename=|DataDirectory|\Database1.mdf; InitialCatalog=UserDate; Integrated Security=True 參數說明: Data Source表示數據源,其值為伺服器地址和實例名,如果是正式版則不用加SQLEXPRESS,如果是免費版,必須加上SQLEXPRESS,即連接本機可以寫成“.\ SQLEXPRESS”; AttchDBFilename表示附加資料庫,其值為附加資料庫的地址,DataDirectory代表當前項目目錄下的App_data目錄,是資料庫的預設存儲路徑; Initial Catalog為資料庫,其值為當前連接所要連接的資料庫名稱 註:如果要使用Sqlconnection對象,必須導入System.Data.Sqlclient命名空間 ADO.NET中的連接等資源都實現了IDisposable介面,可以使用using進行資源管理。也可以使用try……catch語句塊括起來,但是using是最簡單的。 代碼語句:
using (SqlConnection con = new SqlConnection("Data Source=localhost;Initial Catalog=UserDate;Integrated Security=True")) { 程式語句塊; }
或者:
SqlConnection cnn = new SqlConnection();//創建SqlConnection對象的一個實例 cnn.ConnectionString = "Data Source=localhost;Initial Catalog=UserDate;Integrated Security=True"; cnn.Open();
註:using的作用是及時的釋放資源,在花括弧結束的時候,程式會自動釋放語句所申請的記憶體,以達到程式的最優。 一、通過SqlCommand對象執行SQL語句 SqlCommand對象可以執行SQL語句完成對資料庫的增、刪、改、查等數據操作。在SqlCommand類中,最主要的屬性有CommandText,該屬性用於接收要執行的SQL語句,例如cmd.CommandText = "INSERT INTOb1(name, company, position, shijian) VALUES(@Name, @Company, @Position,@Datetime)",除了CommandText屬性,主要還有Connection屬性,用來接收資料庫連接,還有Transaction屬性,用來接收事物。 其還有三個比較常用的方法,第一個是ExecuteNonQuery()方法,主要用來提交無查詢結果的SQL語句,如UPDATE,INSERT,DELETE等語句,其返回值為資料庫中被SQL語句影響的行數,第二個是ExecuteReader()方法,主要用來提交SELECT語句,返回值是一個數據流,裡面是SELECT語句的查詢結果,可以用SqlDataReader對象來接收,然後調用其Read()方法來逐行讀出查詢結果。第三個是ExexuteScalar()方法,主要也是用來提交SELECT語句,但是其返回值是查詢結果的第一行第一列,所以適用於例如COUNT等聚合查詢。 二、SQL註入與參數化查詢 SQL註入是通過特殊的SQL語句非法獲取資料庫的內容。為了保證系統不被黑客進行SQL註入攻擊,在SqlCommand執行SQL語句時,可以對提交的數據先進行參數化處理,參數化處理主要是通過SqlCommand對象的Parameters屬性的Add方法來完成,參數化處理有兩種方法,第一種既是在“執行Insert操作”中提到的,還有另外一種代碼如下:
cmd.CommandText = "INSERT INTO b1(name, company, position, shijian) VALUES(@Name, @Company, @Position, @Datetime)"; cmd.Parameters.Add(new SqlParameter("Name", Name.Text)); cmd.Parameters.Add(new SqlParameter("Company", Company.Text)); cmd.Parameters.Add(new SqlParameter("Position", Position.Text)); cmd.Parameters.Add(new SqlParameter("Datetime", DateTime.Parse(Datetime.Text))); cmd.ExecuteNonQuery();註:以上的代碼中需要註意一點,在第一種代碼中,顯示的對各個參數的數據進行了定義,但是在上面這種代碼中,並未對參數進行數據定義,所以需要在提供數據時對數據進行適時的轉換,例如“shijian”在資料庫中定義為DateTime類型,但是其在文本框中獲得的為string類型,所以需要調用DateTime的Parse方法對數據進行轉換,如果資料庫中的數據是int型,在賦值時也應進行相應的轉換。 三、執行Insert操作 首先,需要申明一個SqlCommand對象; 其次,用SqlConnection的CreateCommand()函數,創建一個SqlCommand對象,然後將所要執行的SQL語句賦值給SqlCommand的CommandText屬性; 最後,調用SqlCommand類的ExexuteNonQuery()方法,執行CommandText的SQL語句。 代碼語句:
using(SqlCommand cmd = con.CreateComand()) { cmd.CommandText = “INSERT INTO b1(name, company, position) VALUES(“whh”, “UVGE”, “coder”)”; cmm.ExecuteNonQuery(); }
或者:
using(SqlCommand cmd = con.CreateComand()) { //設置SQL語句 cmm.CommandText = "INSERT INTO b1(name, company, position, shijian) VALUES(@Name, @Company, @Position, @Datetime)"; //創建參數,並定義其數據類型,要和資料庫中對應的欄位保持相同 cmm.Parameters.Add("@Name", SqlDbType.NVarChar); cmm.Parameters.Add("@Company", SqlDbType.NVarChar); cmm.Parameters.Add("@Position", SqlDbType.NVarChar); cmm.Parameters.Add("@Datetime", SqlDbType.DateTime); //設置參數的值,這些值來自前段的輸入信息 cmm.Parameters["@Name"].Value = Name.Text; cmm.Parameters["@Company"].Value = Company.Text; cmm.Parameters["@Position"].Value = Position.Text; cmm.Parameters["@Datetime"].Value = Datetime.Text; //執行SQL語句 cmm.ExecuteNonQuery(); }
註: SqlCommand類的ExecuteNonQuery()方法的返回值是當前執行的SQL語句影響的行數 四、執行select語句 首先,申明SqlCommand對象 其次,用SqlConnection的CreateCommand()函數,創建一個SqlCommand對象,然後將所要執行的SQL語句賦值給SqlCommand的CommandText屬性; 第三,調用SqlCommand類的ExecuteReader ()方法,執行CommandText的SQL語句。 第四,申明SqlDataReader對象,並用其承接ExecuteReader ()方法所返回的數據流; 第五,用SqlDataReader類的Read()方法逐行讀取數據流中的逐句,取出其中所需要欄位的數據進行處理 代碼語句:
using(SqlCommand cmd = con.CreateComand()) { Cmd.CommandText = “SELECT語句”; using(SqlDataReader reader = cmd.ExecuteReader()) { While(reader.Read()) { String name = reader.GetString(reader.GetOrdinal(“name”)); //數據處理語句塊; } } }
或者:
using(SqlCommand cmd = con.CreateComand()) { using(SqlDataReader reader = cmd.ExecuteReader()) { While(reader.Read()) { String name = reader.[“name”].ToString(); //數據處理語句塊; } } }註: 1、User是SQL SERVER的關鍵字,在表名中應儘量避免,如果必須是User表,可以用SELECT * FROM [User]這樣的語句來查詢該表的內容 2、SqlCommand 類的ExecuteScalar()方法返回的是查詢結果的第一行第一列的數據 3、在插入數據的同時想要獲得當前插入數據的id(主鍵)號,可以通過output語法和ExecuteScalar方法實現,這是在SQLSERVER 2005以後的版本中都有的,具體語法如下:
cmd.CommandText = “INSERT INTO T_Users(UserName,PassWord) OUTPUT inserted.Id Values(“admin”, “123456”)”; int id = Convert.ToInt32(cmd.ExecuteScalar());五、using和close using對實現了IDisposable介面的類進行了資源管理,只要在其作用域內using就會自動進行資源管理,當程式執行出了其作用範圍,程式會自動close和dispose資源,保證資源的及時釋放和回收。而Close只是關閉了當前的連接或者資源,只要其後沒有dispose,還可以繼續open連接,即close並未釋放資源,只做了關閉處理,當close和dispose連用時,和using作用相同,但考慮到異常處理等情況,所以最好使用using,少用close和dispose。 六、通過數據集操作數據 數據集是最常用的訪問數據的方式,其主要流程是連接資料庫、進行數據查詢、將查詢結果填充到數據集、對數據集中的數據進行展示和操作、將操作後的數據集提交資料庫,通過這一系列操作實現對資料庫的修改,此過程主要通過DataSet、DataAdapter、DataTable、DataRow、DataColumn、SqlCommandBuilder等類實現。 根據上面所說到過程,逐步分析: 1、數據查詢,這裡的數據查詢不再是通過Command對象實現,而是通過DataAdapter類的實例來實現,具體代碼如下:
SqlDataAdapter sqldadp = new SqlDataAdapter("SELECT name, company, position, shijian FROM [UserDate].[dbo].[b1] WHERE shijian > '2010-01-21'", con)上面的代碼裡面的con是SqlConnection對象的實例,即資料庫鏈接 2、將數據填充到數據集,數據集也就是DataSet對象的實例了,代碼如下:
DataSet order_daset = new DataSet();//創建DataSet對象實例 sqldadp.Fill(order_daset);//填充DataSet對象註意填充語句中的參數以及方法,是用SqlDataAdapter對象的實例來填充DataSet對象的實例 3、對數據集中的數據進行展示和操作,這步也是這項技術中最重要、最麻煩的一步,主要是通過DataTable對象的實例對數據進行展示和修改,而DataTable類具有很多的屬性和方法,常用的屬性有:Columns能夠得到數據集中的欄位的數據類型、大小、欄位名等信息,DataSet能夠獲得當前DataTable實例所屬的數據集,Rows可以通過下標及欄位名(類似於二維數組)的方式獲得指定行列的數據,常用的方法有:NewRow()方法能夠創建一個空白行,可以在添加數據的時候使用,AcceptChanges()方法能夠將數據表中修改提交給資料庫,Clear()方法可以清楚DataTable對象中的所有數據。具體代碼如下:
DataTable dt = new DataTable();//創建數據表對象 dt = order_daset.Tables[0];//填充數據表 Response.Write("<table border='1'><tr><th>姓名</th><th>公司</th><th>職位</th><th>入職時間</th></tr>"); for (int i = 0; i < dt.Rows.Count; i++) { //按照欄位,逐行取出數據表中的內容並顯示在頁面上 Response.Write("<tr>"); Response.Write("<td>"+dt.Rows[i]["name"].ToString()+"</td>"); Response.Write("<td>"+dt.Rows[i]["company"].ToString()+"</td>"); Response.Write("<td>"+dt.Rows[i]["position"].ToString()+"</td>"); Response.Write("<td>"+DateTime.Parse(dt.Rows[i]["shijian"].ToString()).ToString("yyyy-MM-dd") + "</td>"); Response.Write("</tr>"); } Response.Write("</table>");
註:上面的代碼主要是數據集的展示功能,需要註意的是填充數據表的語句,是由DataSet對象的Tables屬性的下標為0的數據表填充的,這點是非常重要的。
下麵來看看對數據集的修改並且提交資料庫,對數據集的修改,可以通過DataRow以及SqlCommandBuilder對象的實例來實現,SqlCommandBuilder的作用是根據DataAdapter對象自動生成INSERT、UPDATE、DELETE語句,從而使DataAdapter對象更新資料庫內容。具體代碼如下:
//創建DataAdapter對象實例 SqlDataAdapter sqldadp = new SqlDataAdapter("SELECT name, company, position, shijian FROM [UserDate].[dbo].[b1]", con); SqlCommandBuilder scb = new SqlCommandBuilder(sqldadp);//生成插入、刪除、更新語句 DataSet ds = new DataSet();//創建DataSet對象 sqldadp.Fill(ds);//填充DataSet DataRow Myrow = ds.Tables[0].NewRow();//在數據表中創建新的空白記錄對象 //從前臺頁面接受要插入的數據 Myrow["name"] = Name.Text; Myrow["company"] = Company.Text; Myrow["position"] = Position.Text; Myrow["shijian"] = Datetime.Text; //將接收到的數據添加到DataTable中 ds.Tables[0].Rows.Add(Myrow); //更新資料庫中的內容 sqldadp.Update(ds); Response.Write("添加成功!<br>");
註:上面的代碼中最關鍵的一個方法是SqlDataAdapter對象的Update()方法,這個方法的作用是將對數據集所作的改變提交給資料庫,這部分代碼與上面的展示代碼所不同的是DataRow對象的實例所接收的是DataTable中的一行,而不是整個DataTable,其代碼為:DataRow Myrow =ds.Tables[0].NewRow(),這句話就是說在原有的DataTable的基礎上創建一個新的空行,而下麵的代碼則是為這個空行賦值並提交更新,同樣的,如果是更新數據的話,也是獲得DataTable的某一行後,然後對其中的數據進行賦值修改,然後提交,如果是刪除操作,則是通過DataTable獲取某行後,用DataRow接受,然後再調用DataTable的Rows屬性的Remove方法刪除,具體如下代碼:
DataTable dt = ds.Tables[0]; dt.Rows.Remove(Myrow);
七、網路數據的事務處理 事務處理是為了防止在網路上多用戶對資料庫的併發操作破壞數據的一致性和完整性,而事務處理主要通過SqlTransaction對象完成,其主要的方法有:Commit()方法主要負責提交事務處理完成真正的資料庫查詢更新操作,Rollback()方法主要負責當數據查詢更新等資料庫操作出現異常時的事務回滾。ADO.NET的事務處理主要通過SqlCommand對象來實現事務對象,代碼如下:
using (SqlConnection con = new SqlConnection("Data Source = localhost; Initial Catalog = UserDate; Integrated Security = True")) { SqlTransaction transql = null;//申明SqlTransaction對象的實例 SqlCommand cmd = new SqlCommand(); try { con.Open();//創建資料庫鏈接 transql = con.BeginTransaction();//開始事務處理 cmd.Connection = con;//設置Command對象的鏈接 cmd.Transaction = transql;//設置Command對象的事務 //設置帶參數的SQL語句 cmd.CommandText = "INSERT INTO b1(name, company, position, shijian) VALUES(@Name, @Company, @Position, @Datetime)"; //為參數賦值(註意參數在資料庫中的數據類型) cmd.Parameters.Add(new SqlParameter("Name", Name.Text)); cmd.Parameters.Add(new SqlParameter("Company", Company.Text)); cmd.Parameters.Add(new SqlParameter("Position", Position.Text)); cmd.Parameters.Add(new SqlParameter("Datetime", DateTime.Parse(Datetime.Text)));//註意數據類型轉換 //執行SQL語句 cmd.ExecuteNonQuery(); //提交事務 transql.Commit(); Response.Write("添加成功!<br>"); } catch { //如果程式拋出異常則做事務回滾 transql.Rollback(); } }
註:在上面的代碼中,特別要註意SqlTransaction的實例接收的是SqlConnection實例的BeginTransaction()的返回值,SqlCommand的實例的Transaction屬性接收的是SqlTransaction的實例,即SqlConnection實例的BeginTransaction()的返回值,而整個事務的過程是由SqlCommand實例來書寫的,也就是說,在SqlCommand實例裡面的代碼相對應的事務都由SqlTransaction的實例自動生成,前提是必須要有transql = con.BeginTransaction();cmd.Transaction= transql;這兩句代碼,最後用SqlTransaction的Commit()方法或者Rollback()對事務進行提交或者回滾