Ado.net五大對象 連接數據庫並存取數據的幾種方式


一、先了解如下兩張官方的圖解

圖1

圖2

以上這兩張圖都是描述Ado.NET的工作原理。

1.應用程序讀取數據共有三種方式:

(1)直接通過Command對象讀取(但一次只能對一條數據,即表的一行),讀完后不斷開連接。

(2)通過DataReader對象讀取(類似單向管道似的,一條一條的讀數據),讀完后不斷開連接。

(3)通過DataAdapter一次讀一堆數據(這個堆就是DataSet),讀完后就斷開數據庫連接了。

2.應用程序更新和插入數據共有兩種方式:

由於DataReader是單向的,所有不能用於插入和更新數據,只能從數據庫讀取數據,所以應用程序更新和插入數據只有上面的(1)和(3)兩者方式。

從Ado.Net的工作原理圖可以看出,不管用哪種方式和數據庫打交道,都必須有三個的東西:Connection,Command和Sql語句。

 

二、具體工作原理請參照下面圖解:

第(1)種方式如下圖:

圖(1)

圖中把工廠比喻成數據庫,把商城倉庫比喻成應用程序所在內存,把Command比喻成取貨員“二愣子”(因為他比較笨),把Sql語句比喻成訂單,把橋比喻成數據庫連接對象。

第(1)方式的工作過程就是,首先要j架設好橋,然后二愣子拿到訂單(Sql語句)后,就往工廠跑,把訂單給工廠管理員,取回訂單所需的貨物(數據)后,再折返回來把貨物放入倉庫(內存)。但是由於一個人的力量有限,二愣子來回跑的過程中,一個來回只能搬回一件貨物。這時候連接不能斷(橋不能拆),因為每次需要取一件貨物的時候,二愣子都需要來回跑。

方式(1)的總體印象就是,“二愣子”不斷的來回跑。

 

第(2)種方式的工作過程就是,架設好橋后,二愣子拿着“訂單”往工廠跑,但這次的訂單比較復雜,他相當於一份合同,要求和工廠建立一個管道,倉庫需要什么貨物,直接操作管道的一頭的控制按鈕,則管道另一頭會自動提取需要的貨物並通過管道輸送到倉庫。這樣“二愣子”就只需要跑一趟就行了(這份工作輕松、高興!)。這時候連接也不能斷(管道不能斷),只有保持連接才能不斷的一件件從工廠取貨物並通過管道輸送到倉庫。

方式(2)的總體印象就是,有一天單向管道。

如下圖:

圖(2)

第(3)種方式的工作過程就是,架設好橋后,二愣子拿着“訂單”開着車往工廠跑,但這次訂單要求的貨物比較多,工廠就把這一堆貨物幫二愣子裝上車,二愣子高高興興的開着車兜着風把這一堆貨物運回去。這次二愣子不僅能兜風,而且也只跑一趟(這份工作真拉風!)。車開回來后就可以斷開連接了(完全可以把橋拆了),因為需要的所有貨物都已經通過貨車運回來了。此時,貨車就比喻為DataAdapter對象,DataSet對象就比喻成貨車拉回來的那“一堆貨物的集合”。

方式(3)的總體印象就是,“二愣子”開着貨車。

見下圖:

圖(3)

 另外,網上有一個更好看點的圖(意義和上圖一樣),如下:

 

總結:從上面的圖可以看出,無論用什么方式取貨物都必須有三個東西參與才能完成:橋,二愣子,訂單。即:Connection,Command和Sql語句。實際上在使用DataAdapter的時候可能看不到Command對象,其實DataAdapter也是必須通過Command對象取貨物的,只不過DataAdapter內部自己有Command對象而已,DataAdapter使用自己內部的Command對象(這點從最上面的Ado.net原理圖可以看出)。

取貨物就是從數據庫中取數據,更新和插入數據到數據庫的過程和取數據一樣,也需要Connection,Command和Sql語句這三個東西,此不贅述。

 

具體代碼如下:

假設配置文件如下:

<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="Northwind" providerName ="System.Data.SqlClient" connectionString ="server=(local); integrated security = SSPI; database = Northwind" /> </connectionStrings> </configuration>

(1)直接通過Command對象讀取(但一次只能對一條數據,即表的一行),讀完后不斷開連接。

第一步:建立Connection對象(橋)

string connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString(); //從配置文件中取出連接字符串

SqlConnection conn = new SqlConnection(connectionString);        conn.Open();  //打開連接

第二步:建立SQL語句(訂單)

string sqlStr=“ Select * from Student where ID=’10’ ”;

第三步:建立Command對象(二愣子),用這個對象直接返回一個行數據。

SQLCommand cmd=new SQLCommand(sqlStr,conn); //參數就是sql語句和連接對象

//注意通過new Command對象的連個參數把這三個必須的東西聯系在一起了。

下面就是執行Command對象的方法了,共有三種方法:

int  LineCount=cmd.ExecuteNonQuery();  //一般用於更新和插入語句,不返回查詢結果,但這個函數的返回值本身返回影響的行數。

DataReader  dr=cmd.ExecuteReader(); //一般用於Select語句返回查詢的數據,然后通過DataReader一個個的讀取。【建立管道】

int  OneValue=cmd.ExecuteScaler(); //一般用於Select查詢,但返回結果為一個值的情況,比如SQL語法中的Count函數和Sum函數。這也印證了二愣子力量有限,僅憑自己的力量一次只能搬回一件貨物,或者不搬回貨物,僅通知數據庫更新和插入一個數據。

總之,更新和插入用ExecuteNonQuery,查詢主要使用ExecuteReader,特殊情況(只返回單個值)才用ExecuteScaler。

當然,直接用Command對象讀取數據就只有ExecuteNonQuery和ExecuteScaler兩種方法,建立管道方法屬於下面(2)的方法。

最后別忘了關閉連接,conn.Close();

 

(2)通過DataReader對象讀取(類似單向管道似的,一條一條的讀數據),讀完后不斷開連接。

第一步:建立Connection對象(橋)      

string myconn=”Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind”;

SqlConnection conn=new SqlConnection(myconn);        

第二步:建立SQL語句(訂單)

string MySQL=”select OrderID,CustomerID from Orders where CustomerID=’CHOPS’”;

第三步:建立Command對象(二愣子),但用這個對象返回一個管道DataReader  

SqlCommand cmd=new(mysql,conn);       conn.Open();  //打開數據庫連接,用之前打開就行,放在哪無所謂
 //通過SqlCommand的ExecuteReader()方法構造DataReader 對象。
SqlDataReader myreader=cmd.ExecuteReader();
while(myreader.read()){
  Console.WriteLine(myreader.GetInt32(0)+”,”+myreader.GetString(1));

}
myreader.Close();
myconnection.Close();

補充:SqlDataReader讀數據方法有兩大類,帶小括號的函數和帶中括號的索引屬性

帶小括號的有,GetInt32(), GetString()等,參數都是int類型,表示列號,也只能使用列號。

帶中括號的有,直接帶上中括號,有myreader[0] 和 myreader[“ID”]兩種,即可以使用列號,也可以使用列名。

 

(3)通過DataAdapter一次讀一堆數據(這個堆就是DataSet),讀完后就斷開數據庫連接了。

第一步:建立Connection對象(橋)

string connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString(); //從配置文件中取出連接字符串

SqlConnection conn = new SqlConnection(connectionString);        conn.Open();  //打開連接

第二步:建立SQL語句(訂單)

string sqlStr=“ Select * from Student where ID=’10’ ”;

第三步:建立DataAdapter對象(這個對象內部隱式的建立了Command對象),即建立好貨車就行了,貨車內部有人。但通過這個對象填充DataSet,DataSet在本地內存中

SqlDataAdapter da=new SqlDataAdapter(sqlStr,conn);  //參數仍然是sql語句和連接對象

DataSet ds=new DataSet();

ds.Fill(ds,”表名”);

 

使用參數的Sql語句,即使用Paramerter對象例子如下:

這里使用SqlParamerter對象,這個對象是SqlParamerters集合的子元素,每個Command對象都有一個Parameters屬性。【就好像二愣子不僅拿着訂單,還拿着訂單中每樣貨物對應的更詳細的貨物描述的表單。】

下面代碼目的是根據已知的名字和密碼獲取年齡大小。

string name = “Tim”;

string pwd =”123456”;

string Age;

string constr = @”server=.\sqlexpress;database=MyDataBase;uid=sa;pwd=sa”;

using (SqlConnection sqlconn = new SqlConnection(constr))  //第一步,建立連接對象

{

         //參數化查詢1

        string cmdstr = @”select age from loginn where uname=@name1 and upwd=@pwd1”; 

        //第二步,建立Sql語句。 @name1,@pwd1僅僅是別名而已,相當於局部變量

        using (SqlCommand cmd =new SqlCommand(cmdstr, sqlconn))   //第三步,建立Command對象

                {

                        //加參數

                       cmd.Parameters.Add(new SqlParameter(”@name1”, name));

                        //把name中的值賦給@name

                       cmd.Parameters.Add(new SqlParameter(”@pwd1”, pwd));//注意Add方法中是new了一個 SqlParameter

                       // cmd.Parameters.AddWithValue(“@pwd1”, pwd);//此方法內部實現同Add,推薦用前者

                       if (sqlconn.State == ConnectionState.Closed)

                               {

                                        sqlconn.Open();

                                        Age=cmd.ExecuteScalar();    //獲取年齡

                                       //由於是查詢且age字段是int類型,且Sql語句返回一個單值,所以用ExecuteScalar最方便。 否則就需要用ExecuteReader。       

                                }  //end if           

                  }  //end using

}  //end using

 

 

使用存儲過程的例子如下:

轉自:http://www.cnblogs.com/herbert/archive/2010/07/12/1775889.html

ADO.NET中調用存儲過程

此時,存儲過程就看成一種特色類型的訂單,也就是通知二愣子手里拿的訂單是個“存儲過程”類型的訂單,另外這種訂單也需要“更詳細的貨物描述的表單”,所以也需要參數,其他的就和普通帶參數的訂單的執行過程一模一樣了,需要注意的是一般使用Command對象的ExecuteNonQuery方法執行存儲過程。

下面這個例子展示如何在ADO.NET調用存儲過程。我只選擇了一種方式,說實話不太喜歡多樣化的方式去處理問題,這種發散式的做法在編程中似乎沒有必要。選擇自己喜歡的一種方式。

這里SQL Server有一個樣本數據庫Northwind.

以Northwind里的Region表為例:

Region表有2個字段:

  • RegionID, int 主鍵
  • RegionDescription, nchar(50)

寫以下幾個存儲過程:

RegionUpdate: 多個參數

CREATE PROCEDURE RegionUpdate(@RegionID INTEGER, @RegionDescription NCHAR(50)) AS SET NOCOUNT OFF UPDATE Region SET RegionDescription = @RegionDescription WHERE RegionID = @RegionID

GO
 

RegionDelete 一個參數

CREATE PROCEDURE RegionUpdate(@RegionID INTEGER) AS SET NOCOUNT OFF DELETE FROM Region WHERE RegionID = @RegionID GO

RegionInsert 帶返回參數

CREATE PROCEDURE RegionInsert(@RegionDescription NCHAR(50), @RegionID INTEGER OUTPUT) AS SET NOCOUNT OFF SELECT @RegionID = MAX(RegionID) + 1 FROM Region INSERT INTO Region VALUES(@RegionID, @RegionDescription) GO 

 

工程添加下面的配置文件

App.configuration

<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="Northwind" providerName ="System.Data.SqlClient" connectionString ="server=(local); integrated security = SSPI; database = Northwind" /> </connectionStrings> </configuration>

 

下面是C# code:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Configuration; using System.Data.SqlClient; namespace SQLProcedureDemo { class Program { private static string GetConnectionStringsConfig(string connectionName) { string connectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString(); Console.WriteLine(connectionString); return connectionString; } static void Main(string[] args) { string source = GetConnectionStringsConfig("Northwind"); try { using (SqlConnection conn = new SqlConnection(source)) { conn.Open(); // Invoke RegionUpdate Procedure SqlCommand cmd = new SqlCommand("RegionUpdate", conn); cmd.CommandType = CommandType.StoredProcedure; SqlParameter updatepara1 = new SqlParameter("@RegionID", SqlDbType.Int); updatepara1.Value = 3; cmd.Parameters.Add(updatepara1); SqlParameter updatepara2 = new SqlParameter("@RegionDescription", SqlDbType.NChar); updatepara2.Value = "Northern"; cmd.Parameters.Add(updatepara2); // You can also use the following statement //cmd.Parameters.AddWithValue("@RegionID", 3); //cmd.Parameters.AddWithValue("@RegionDescription", "Northern"); cmd.ExecuteNonQuery(); // Invoke RegionDelete Procedure SqlCommand cmdDel = new SqlCommand("RegionDelete", conn); cmdDel.CommandType = CommandType.StoredProcedure; SqlParameter myParameter = new SqlParameter("@RegionID", SqlDbType.Int); myParameter.Value =5; cmdDel.Parameters.Add(myParameter); cmdDel.ExecuteNonQuery(); // Invoke RegionInsert Procedure SqlCommand cmdInsert = new SqlCommand("RegionInsert", conn); cmdInsert.CommandType = CommandType.StoredProcedure; SqlParameter para1 = new SqlParameter("@RegionDescription", SqlDbType.NChar); para1.Value = "South West"; cmdInsert.Parameters.Add(para1); SqlParameter para2 = new SqlParameter("@RegionID", SqlDbType.Int); para2.Direction = ParameterDirection.Output; cmdInsert.Parameters.Add(para2); cmdInsert.ExecuteNonQuery(); int newRegionID = (int)cmdInsert.Parameters["@RegionID"].Value; Console.WriteLine(newRegionID); conn.Close(); } } catch (SqlException ex) { // Console.WriteLine(ex.Message); } Console.ReadKey(); } } }


免責聲明!

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



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