Ado.Net 資料庫訪問技術(.Net 6版本)

来源:https://www.cnblogs.com/xuyubing/archive/2023/05/31/17445868.html
-Advertisement-
Play Games

1. ADO.NET的前世今生 ADO.NET的名稱起源於ADO(ActiveX Data Objects),是一個COM組件庫,用於在以往的Microsoft技術中訪問數據。之所以使用ADO.NET名稱,是因為Microsoft希望表明,這是在NET編程環境中優先使用的數據訪問介面。 ADO.NE ...


1. ADO.NET的前世今生

ADO.NET的名稱起源於ADO(ActiveX Data Objects),是一個COM組件庫,用於在以往的Microsoft技術中訪問數據。之所以使用ADO.NET名稱,是因為Microsoft希望表明,這是在NET編程環境中優先使用的數據訪問介面。

ADO.NET可讓開發人員以一致的方式存取資料來源(例如 SQL Server 與 XML),以及透過 OLE DB 和 ODBC 所公開的資料來源。資料共用的消費者應用程式可使用ADO.NET 來連接至這些資料來源,並且擷取、處理及更新其中所含的資料。

ADO.NETt可將資料管理的資料存取分成不連續的元件,這些元件可分開使用,也可串聯使用ADO.NET也包含 .NET Framework 資料提供者,以用於連接資料庫、執行命令和擷取結果。這些結果會直接處理、放入ADO.NET DataSet 物件中以便利用機器操作 (Ad Hoc)的方式公開給使用者、與多個來源的資料結合,或在各層之間進行傳遞。DataSet 物件也可以與.NET Framework 資料提供者分開使用,以便管理應用程式本機的資料或來自 XML 的資料。

ADO.NET類別 (Class) 位於 System.Data.dll 中,而且會與 System.Xml.dll 中的XML 類別整合。

ADO.NET可為撰寫 Managed 程式碼的開發人員提供類似於ActiveX Data Objects (ADO)提供給原生元件物件模型 (Component Object Model,COM)開發人員的功能。建議使用ADO.NET而非ADO來存取.NET 應用程式中的資料。

ADO .NET會提供最直接的方法,讓開發人員在 .NET Framework 中進行資料存取。

 

現階段我們以SqlServer 為案例進行講解。

 

Ado.Net 優點

執行效率高。任何ORM框架(對象關係映射,理解為一種可提高訪問資料庫開發效率的一種框架),在Ado.net 面前都是弟弟, ado.net 作為原裝的直接跟資料庫打交道,直接操作資料庫,沒有進行額外的封裝。比如我們可以直接執行sql語句,直接調用存儲過程。直接操作DataSet數據集等等數據。

 

缺點:

  1. 開發效率偏慢

  2. 缺乏面向對象思想

 

2. Connection 連接對象

Connection 是資料庫連接對象,用於與資料庫建立連接。SqlServer 連接類是SqlConnection , MySql 的連接類是MySqlConnection, Oracle 資料庫連接類是 OracleConnection ,這些類都實現了IDbConnection介面。

1. SqlConnection 類

  • 命名空間: System.Data.SqlClient

  • 程式集: System.Data.SqlClient.dll

通過Nuget 將 System.Data.SqlClient 程式集引用到項目中

 

構造方法:

SqlConnection()初始化 SqlConnection 類的新實例。
SqlConnection(String) 如果給定包含連接字元串的字元串,則初始化 SqlConnection 類的新實例。
SqlConnection(String, SqlCredential) 在給定連接字元串的情況下,初始化 SqlConnection 類的新實例,該連接字元串不使用 Integrated Security = true 和包含用戶 ID 和密碼的 SqlCredential 對象。

 

屬性:

屬性名描述
ConnectionString 連接字元串
State 只讀,連接狀態
Database 只讀,當前連接的資料庫
ServerVersion 只讀,當前客戶端連接的SQLServer的版本
ConnectionTimeout 嘗試建立連接時終止嘗試並生成錯誤之前所等待的時間(以秒為單位),預設15秒

 

常用方法:

方法名描述
Open() 使用由 ConnectionString 指定的屬性設置打開一個資料庫連接。
Close() 關閉與資料庫之間的連接。 此方法是關閉任何打開連接的首選方法。
Dispose() 執行與釋放或重置非托管資源關聯的應用程式定義的任務。
BeginTransaction() 開始資料庫事務。
BeginTransaction(IsolationLevel) 以指定的隔離級別啟動資料庫事務。
BeginTransaction(IsolationLevel,string) 以指定的隔離級別和事務名稱啟動資料庫事務。
CreateCommand() 創建並返回與 SqlConnection 關聯的 SqlCommand 對象。

 

  1. 使用無參構造:

    SqlConnection connection = new SqlConnection();
    connection.ConnectionString = "server=.;uid=sa;pwd=123456;database=unit21";
    connection.Open();// 打開連接
    ​
    Console.WriteLine($"State={connection.State}");
    Console.WriteLine($"DataBase={connection.Database}");
    Console.WriteLine($"ServerVersion={connection.ServerVersion}");
    Console.WriteLine($"DataSource={connection.DataSource}");
    Console.WriteLine($"ConnectionTimeout={connection.ConnectionTimeout}");
    ​
    connection.Close();// 一定要記得關閉連接

    輸出結果:

    State=Open
    DataBase=unit21
    ServerVersion=14.00.1000
    DataSource=.
    ConnectionTimeout=15
  2. 有參構造

    SqlConnection connection =
    new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21");
    connection.Open();// 打開連接
    ​
    Console.WriteLine($"State={connection.State}");
    Console.WriteLine($"DataBase={connection.Database}");
    Console.WriteLine($"ServerVersion={connection.ServerVersion}");
    Console.WriteLine($"DataSource={connection.DataSource}");
    Console.WriteLine($"ConnectionTimeout={connection.ConnectionTimeout}");
    ​
    connection.Close();// 一定要記得關閉連接

2. 修改超時時間

SqlConnection connection =
new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30;");
connection.Open();
Console.WriteLine($"ConnectionTimeout={connection.ConnectionTimeout}");
connection.Close();

 

輸入結果:

ConnectionTimeout=30

 

3. SqlCredential 類

提供了更安全的方式來指定使用 SQL Server 身份驗證嘗試登錄的密碼。 由用戶 ID 和將用於 SQL Server 身份驗證的密碼構成。 SqlCredential 對象中的密碼是 SecureString 類型(一種加密文本)。

如果調用ChangePassword() 方法修改SqlCredential對象時將會影響連接池 ,因為不對的SqlCredential 實例 將使用不同的連接池,即使用戶 ID 和密碼相同,也是如此 。

如果SqlCredential 對象非空 並且連接字元串中出現如下關鍵字,將會引發 InvalidOperationException 異常:

  • Integrated Security = true

  • Password

  • User ID

  • Context Connection = true

 

winform 案例:

System.Windows.Controls.TextBox txtUserId = new System.Windows.Controls.TextBox();  
System.Windows.Controls.PasswordBox txtPwd = new System.Windows.Controls.PasswordBox();  
​
​
SqlConnection conn = new SqlConnection("server=.;database=unit21;");
SecureString pwd = txtPwd.SecurePassword;  
pwd.MakeReadOnly();  
SqlCredential cred = new SqlCredential(txtUserId.Text, pwd);  
conn.Credential = cred;  
conn.Open();  
// ...
conn.close();

3. 自動釋放(推薦)

using

實現了IDispose 介面的類,都可以使用using 來實現自動釋放資源功能。

/* *
 * using : 引用命名空間
 * using: 釋放資源
 *
 * 1. 為什麼以前我們定義的變數不需要釋放資源呢?
 * GC: 垃圾回收器,這裡面封裝了一些演算法規定了什麼時候去回收資源。我們自己定義一些變數,不需要關心它有沒有釋放掉,因為GC會幫我們自動回收資源
 *
 * 2. 既然已經有了GC,為什麼還需要手動的釋放資源呢?
 * 答:GC 只能回收托管資源(由.Net CLR管理的資源),而SqlConnection是屬於非托管資源
 *
 * 3. 我怎麼知道它是非托管?
 * 答:如果它實現了IDisposable 介面,那麼我們就可以使用using 來手動的釋放資源了
 */using (SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30"))
{
    connection.Open();// 打開連接
    Console.WriteLine($"State={connection.State}");
    Console.WriteLine($"DataBase={connection.Database}");
    Console.WriteLine($"ServerVersion={connection.ServerVersion}");
    Console.WriteLine($"DataSource={connection.DataSource}");
    Console.WriteLine($"ConnectionTimeout={connection.ConnectionTimeout}");
} // 並未調用close()方法,但會自動關閉

 

C# 7.0 以後的語法:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();// 打開連接
Console.WriteLine($"State={connection.State}");
Console.WriteLine($"DataBase={connection.Database}");
Console.WriteLine($"ServerVersion={connection.ServerVersion}");
Console.WriteLine($"DataSource={connection.DataSource}");
Console.WriteLine($"ConnectionTimeout={connection.ConnectionTimeout}");

connection 會在它當前的代碼塊結束處(作用域的結尾)自動調用關閉連接代碼。

 

4. Command 命令對象

Command 是資料庫命令對象,它是資料庫執行的一個 Transact-SQL 語句或存儲過程 。SqlServer 連接類是SqlCommand , MySql 的連接類是MySqlCommand, Oracle 資料庫連接類是 OracleCommand ,這些類都實現了IDbCommand介面。

 

1. SqlCommand 類

  • 命名空間: System.Data.SqlClient

  • 程式集: System.Data.SqlClient.dll

 

構造方法:

SqlCommand()初始化 SqlCommand 類的新實例。
SqlCommand(String) 使用查詢的文本初始化 SqlCommand 類的新實例。
SqlCommand(String, SqlConnection) 使用查詢的文本和 SqlConnection 初始化 SqlCommand 類的新實例。
SqlCommand(String, SqlConnection, SqlTransaction) 使用查詢文本、SqlConnection 以及 SqlTransaction 初始化 SqlCommand 類的新實例。

常用屬性:

CommandText獲取或設置要在數據源中執行的 Transact-SQL 語句、表名或存儲過程。
CommandTimeout 獲取或設置在終止嘗試執行命令並生成錯誤之前的等待時間(以秒為單位)。
CommandType 獲取或設置一個值,該值指示解釋 CommandText 屬性的方式。
Connection 獲取或設置 SqlCommand 的此實例使用的 SqlConnection
Parameters 獲取 SqlParameterCollection
Transaction 獲取或設置要在其中執行 SqlTransactionSqlCommand

常用方法:

方法名描述
Cancel() 嘗試取消 SqlCommand 的執行。
CreateParameter() 創建 SqlParameter 對象的新實例。
Dispose() 執行與釋放或重置非托管資源關聯的應用程式定義的任務。(繼承自 DbCommand)
Dispose(Boolean) 釋放由 DbCommand 占用的非托管資源,還可以另外再釋放托管資源。(繼承自 DbCommand)
ExecuteNonQuery() 對連接執行 Transact-SQL 語句並返回受影響的行數。
ExecuteScalar() 執行查詢,並返回查詢所返回的結果集中第一行的第一列。 忽略其他列或行。
ExecuteReader() CommandText 發送到 Connection,並生成 SqlDataReader

 

案例1:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();
using SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = $"insert into product values('枸杞',18)";
cmd.ExecuteNonQuery();// 執行

案例2:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();
using SqlCommand cmd = new SqlCommand("select count(id) from product");
cmd.Connection = connection;
object count = cmd.ExecuteScalar();// 獲取首行首列

案例3:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();
using SqlCommand cmd = new SqlCommand("select * from product",connection);
using SqlDataReader dataReader = cmd.ExecuteReader(); // 返回一個讀取對象

5. SqlDataReader 數據讀取

提供一種從 SQL Server 資料庫中讀取只進的行流的方式 。 在讀取數據的過程中需要一直與資料庫保持連接,適合數據量小的情況,執行效率還是可以的。 我們將SqlDataReader 讀取數據的方式稱為連接模式

  • 命名空間: System.Data.SqlClient

  • 程式集: System.Data.SqlClient.dll

     

屬性

Connection獲取與 SqlConnection 關聯的 SqlDataReader
Depth 獲取一個值,用於指示當前行的嵌套深度。
FieldCount 獲取當前行中的列數。
HasRows 獲取一個值,該值指示 SqlDataReader 是否包含一行還是多行。
IsClosed 檢索一個布爾值,該值指示是否已關閉指定的 SqlDataReader 實例。
Item[Int32] 在給定列序號的情況下,獲取指定列的以本機格式表示的值。
Item[String] 在給定列名稱的情況下,獲取指定列的以本機格式表示的值。
RecordsAffected 獲取執行 Transact-SQL 語句所更改、插入或刪除的行數。
VisibleFieldCount 獲取 SqlDataReader 中未隱藏的欄位的數目。

方法

Close()關閉 DbDataReader 對象。
Dispose() 釋放 DbDataReader 類的當前實例所使用的所有資源。
GetName(Int32) 獲取指定列的名稱。
GetOrdinal(String) 在給定列名時獲取相應的列序號。
Read() SqlDataReader 前進到下一條記錄,返回bool。

還有很多方法,他們都是根據列序列號獲取指定列的功能,如:GetInt(int index),GetFloat(int index),GetDateTime(int index),GetString(int index) .....

案例

案例1:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();
using SqlCommand cmd = new SqlCommand("select * from product",connection);
using SqlDataReader dataReader = cmd.ExecuteReader();
​
while (dataReader.Read())
{
    object id = dataReader.GetValue("id");
    object pname = dataReader.GetValue("pname");
    object price = dataReader.GetValue("price");
​
    Console.WriteLine($"id: {id}\t pname: {pname}\t price: {price}\t \n");
}

案例2,通過dataReader 索引讀取:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();
using SqlCommand cmd = new SqlCommand("select * from product",connection);
using SqlDataReader dataReader = cmd.ExecuteReader();
​
while (dataReader.Read())
{
    // 索引下標順序必須與資料庫列順序一致
    object id = dataReader[0];
    object pname = dataReader[1];
    object price = dataReader[2];
​
    Console.WriteLine($"id: {id}\t pname: {pname}\t price: {price}\t \n");
}

 

案例3,封裝成對象:

using SqlConnection connection = new SqlConnection("server=.;uid=sa;pwd=123456;database=unit21;timeout=30");
connection.Open();
using SqlCommand cmd = new SqlCommand("select * from product",connection);
using SqlDataReader dataReader = cmd.ExecuteReader();
​
while (dataReader.Read())
{
    // 索引下標順序必須與資料庫列順序一致
    Product product = new Product(
        dataReader.GetInt32(0),
        dataReader.GetString(1),
        dataReader.GetInt32(2)
    );
​
    Console.WriteLine($"id: {product.Id}\t pname: {product.Name}\t price: {product.Price}\t \n");
}
​
record Product(int Id,string Name,int Price);

6. SqlDataAdapter 適配器

適配器詳細介紹

  • 命名空間: System.Data.SqlClient

  • 程式集: System.Data.SqlClient.dll

表示用於填充 DataSet (表示數據的記憶體中的資料庫,它可以由多個table組成)和更新 SQL Server 資料庫的一組數據命令和一個資料庫連接。 適配器模式也被稱為斷開模式。

 

一次連接取得數據之後,即可斷開,在用戶非常多的情況下,不會占用太多的連接池資源。 還有一點,就是一次性的從資料庫中取得了數據之後,這些數據是存在記憶體中的,而不會再去操作資料庫,所以你對這些數據做任何的操作,都只是修改記憶體,不會改變資料庫中的內容。

 

構造方法:

SqlDataAdapter()初始化 SqlDataAdapter 類的新實例。
SqlDataAdapter(SqlCommand) 初始化 SqlDataAdapter 類的新實例,用指定的 SqlCommand 作為 SelectCommand 的屬性。
SqlDataAdapter(String, SqlConnection) 使用 SqlDataAdapterSelectCommand 對象初始化 SqlConnection 類的一個新實例(用得最多)。
SqlDataAdapter(String, String) SqlDataAdapter 和一個連接字元串初始化 SelectCommand 類的一個新實例。

屬性:

DeleteCommand獲取或設置一個 Transact-SQL 語句或存儲過程,以從數據集刪除記錄。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 裝飾器在 Python 中扮演了重要的角色,這是一種精巧的語言特性,讓我們能夠修改或增強函數和類的行為,無需修改它們的源代碼。這篇文章將深入探討裝飾器的所有相關主題,包括裝飾器的基礎知識、實現與使用、工作原理,以及通過實際例子學習裝飾器的獨特用法。 ...
  • ## 併發與並行😣 ### 併發與並行的概念和區別 並行:同一個時間段內多個任務同時在不同的CPU核心上執行。強調同一時刻多個任務之間的”**同時執行**“。 併發:同一個時間段內多個任務都在進展。強調多個任務間的”**交替執行**“。 ![](https://img2023.cnblogs.co ...
  • 摘要:在讀多寫少的環境中,有沒有一種比ReadWriteLock更快的鎖呢?有,那就是JDK1.8中新增的StampedLock! 本文分享自華為雲社區《【高併發】高併發場景下一種比讀寫鎖更快的鎖》,作者: 冰 河。 什麼是StampedLock? ReadWriteLock鎖允許多個線程同時讀取共 ...
  • ###BIO:同步阻塞 主線程發起io請求後,需要等待當前io操作完成,才能繼續執行。 ###NIO:同步非阻塞 引入selector、channel、等概念,當主線程發起io請求後,輪詢的查看系統是否準備好執行io操作,沒有準備好則主線程不會阻塞會繼續執行,準備好主線程會阻塞等待io操作完成。 # ...
  • 在前面的幾篇文章中,詳細地給大家介紹了Java里的集合。但在介紹集合時,我們涉及到了泛型的概念卻並沒有詳細學習,所以今天我們要花點時間給大家專門講解什麼是泛型、泛型的作用、用法、特點等內容 ...
  • # Rust Web 全棧開發之 Web Service 中的錯誤處理 ## Web Service 中的統一錯誤處理 ### Actix Web Service 自定義錯誤類型 -> 自定義錯誤轉為 HTTP Response - 資料庫 - 資料庫錯誤 - 串列化 - serde 錯誤 - I/ ...
  • 1. 透過現象看本質 反射被譽為是 c#中的黑科技 ,在很多領域中都有反射的身影,例如,我們經常使用的ORM框架,ABP框架 等。 反射指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。. 程式集包含模塊,而模塊包含類型,類型又包含成員。. 反射則提供了封裝程式集、模塊和類型的對象。. 您可以使 ...
  • 1. 為什麼需要單元測試 在我們之前,測試某些功能是否能夠正常運行時,我們都將代碼寫到Main方法中,當我們測試第二個功能時,我們只能選擇將之前的代碼清掉,重新編寫。此時,如果你還想重新測試你之前的功能時,這時你就顯得有些難為情了,因為代碼都被你清掉了。當然你完全可以把代碼寫到一個記事本中進行記錄, ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...