程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> ASP.NET基礎 >> 在ASP.NET 2.0中操作數據之七十:配置數據庫連接和命令等級設置

在ASP.NET 2.0中操作數據之七十:配置數據庫連接和命令等級設置

編輯:ASP.NET基礎

導言:

  在本系列我們用類型化的DataSets來構建數據訪問層。就像在第一章探討的那樣,類型化DataSets的DataTables用作存儲數據的“倉庫”,而TableAdapters作為連接數據庫的通道,以檢索、修改數據.TableAdapters 將處理數據庫的很多復雜的細節進行了封裝,將我們解脫出來,免去了寫代碼連接數據庫、發出命名、向DataTable填充數據的痛苦.

  不過在某些時候我們需要深入的探究TableAdapter,直接寫代碼處理ADO.NET對象.在第61章《在事務裡對數據庫修改進行封裝》裡我們向TableAdapter添加了多個方法以開啟、提交、回滾ADO.NET事務.這些方法都使用內在的、手動創建的SqlTransaction對象來對TableAdapter的SqlCommand對象進行賦值.

  在本文,我們將考察如何訪問TableAdapter的“數據庫連接”和“數據庫命令”級的設置.具體來說,我們將向ProductsTableAdapter添加函數,以訪問“連接字符串”(connection string)和“命令過期時間”(command timeout)設置.

用ADO.NET處理數據

  微軟.NET Framework包含了很多處理數據的特殊用途的類。這些類用System.Data namespace來進行創建,其中就包括ADO.NET classe類,一些ADO.NET名下的類需要依賴某個特定的data provider才能工作.你可以想象在ADO.NET classes類和某個數據存儲(data store)之間,有一個data provider充當連接通道(communication channel)以供傳遞信息.data provider包括OleDb 、ODBC, 以及其它一些專門設計來連接某種特定數據庫系統的data provider.舉個例子,我們不能用OleDb來連接一個Microsoft SQL Server數據庫.而SqlClient就可以,因為它是經過優化的專門設計來連接SQL Server的.

當編程訪問數據時,通常使用下面的模式:

1.新建數據庫連接
2.發出命令
3.用SELECT查詢來返回記錄

  以上3步每步都有單獨的ADO.NET classes類來執行.比如連接數據庫用SqlConnection class類;要發出INSERT, UPDATE, DELETE,或SELECT命令,用SqlCommand class類.

  除了第61章《在事務裡對數據庫修改進行封裝》外,我們都沒有自己寫任何ADO.NET代碼,因為TableAdapters自動生成的代碼包含了一些必要的功能:連接數據庫、發出命令、檢索數據、填充DataTables.但是有時我們要自己定制這些設置.在接下來的幾步我們將探究TableAdapters內部使用的ADO.NET對象.

第一步:考察Connection屬性

  每個TableAdapter class類都有一個Connection屬性,用於指定數據庫連接信息.該屬性的數據類型以及ConnectionString的值根據TableAdapter設置向導所做的配置而定.我們還記得,當向類型化的DataSet添加一個TableAdapter時,向導要我們指定數據源(見圖1).在下拉列表裡列出了web.config文件指定連接的數據庫,以及服務器資源管理器的Data Connections裡的數據庫.如果我們要連接的數據庫沒有出現在下拉列表裡,點“New Connection”按鈕,以提供必需的連接信息.

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916392498.png
圖1:TableAdapter設置向導的第一步

  我們化點時間來查看TableAdapter的Connection屬性的代碼,就像在第一章《創建一個數據訪問層》裡探討的一樣,我們可以在Class View窗口裡查看自動生成的TableAdapter代碼,轉到相應的類,再雙擊成員名(member name)即可.

  打開“View”菜單,選中“Class View”(或按住Ctrl+Shift+C).在Class View窗口的上半部分裡,選中NorthwindTableAdapters命名空間,再選中ProductsTableAdapter class類.這將在下半部分顯示出ProductsTableAdapter的成員,如圖2所示.雙擊Connection屬性以查看代碼。

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916392574.png
圖2:雙擊Connection以查看自動生成的代碼

TableAdapter的Connection屬性以及其它與連接相關的代碼如下:

private System.Data.SqlClient.SqlConnection _connection;

private void InitConnection() {
 this._connection = new System.Data.SqlClient.SqlConnection();
 this._connection.ConnectionString =
 ConfigurationManager.ConnectionStrings["NORTHWNDConnectionString"].ConnectionString;
}

internal System.Data.SqlClient.SqlConnection Connection {
 get {
 if ((this._connection == null)) {
  this.InitConnection();
 }
 return this._connection;
 }
 set {
 this._connection = value;
 if ((this.Adapter.InsertCommand != null)) {
  this.Adapter.InsertCommand.Connection = value;
 }
 if ((this.Adapter.DeleteCommand != null)) {
  this.Adapter.DeleteCommand.Connection = value;
 }
 if ((this.Adapter.UpdateCommand != null)) {
  this.Adapter.UpdateCommand.Connection = value;
 }
 for (int i = 0; (i < this.CommandCollection.Length); i = (i + 1)) {
  if ((this.CommandCollection[i] != null)) {
  ((System.Data.SqlClient.SqlCommand)
   (this.CommandCollection[i])).Connection = value;
  }
 }
 }
}

  當對TableAdapter class類進行“實例化”(instantiated)時,成員變量_connection的值等同為null.當訪問Connection屬性時,首先檢查是否已經對成員變量_connection實例化,如果沒有的話就調用InitConnection方法,該方法對_connection進行實例化,然後用TableAdapter設置向導指定的連接字符串對其賦值.

  同樣可以用Connection屬性對一個SqlConnection對象賦值,這樣的話就可以將這個新的SqlConnection對象與TableAdapter的SqlCommand對象聯系起來.

第二步:訪問“數據庫連接”級的設置

  數據庫連接信息封裝在TableAdapter內部,很難從應用程序的其它層對其進行訪問.然而,在某些時候,某人查詢、用戶或ASP.NET頁面需要對TableAdapter的連接信息進行訪問或定制.

  讓我們對Northwind數據集的ProductsTableAdapter進行擴展,以包含一個ConnectionString屬性,以便於在業務邏輯層對TableAdapter用到的連接字符串進行讀取和更改.

  注意:一個連接字符串是這樣的一個字符串,它指定了數據庫連接信息.比如,提供者provider、數據庫的位置、身份驗證,以及其它與數據庫相關的設置.更多詳情請參考網站ConnectionStrings.com

  就像在第一章《創建一個數據訪問層》裡討論過的一樣,類型化的DataSet自動生成的類可以通過使用部分類(partial classes)來進行擴充.首先,在~/App_Code/DAL文件夾裡新建一個名為ConnectionAndCommandSettings的文件夾.

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916392520.png
圖3:添加一個名為ConnectionAndCommandSettings的文件夾

在裡面添加一個ProductsTableAdapter.ConnectionAndCommandSettings.cs文件,鍵入如下的代碼:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace NorthwindTableAdapters
{
 public partial class ProductsTableAdapter
 {
 public string ConnectionString
 {
  get
  {
  return this.Connection.ConnectionString;
  }
  set
  {
  this.Connection.ConnectionString = value;
  }
 }
 }
}

  該局部類為ProductsTableAdapter class類添加了一個public類型的,名為ConnectionString的屬性.該屬性允許在任何層對TableAdapter用到的連接字符串進行讀取和更改.

  當創建並保存該局部類後,打開ProductsBLL class類。打開其中的一個方法,鍵入Adapter,再輸入其范圍內的一個關鍵字以打開智能感知,你應該可以看到這個新添加的的ConnectionString屬性出現在智能感知裡,這就表明了我們可以在BLL層通過編程來讀取或更改其值.

訪問整個Connection對象

  該局部類擴展的只是connection對象眾多屬性中的一個:ConnectionString.如果你想在TableAdapter范圍外訪問整個connection對象的話,你可以改變Connection屬性的保護等級.就像我們在第一步考察的那樣,TableAdapter的Connection屬性標明為internal,這就是說,只有在同級的類裡才可以對其進行訪問.不過我們可以通過TableAdapter的 ConnectionModifier屬性來改變其訪問范圍.

  打開Northwind數據集,在ProductsTableAdatper上右鍵單擊,打開屬性窗口,你將會看到ConnectionModifier設置為默認的Assembly. 為了在數據集范圍以外訪問Connection屬性,我們將其改為Public.

https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017010916392558.png
圖4:可以通過ConnectionModifier屬性修改Connection屬性的訪問范圍

  保存後在返回到ProductsBLL class類,就向前面一樣在某個現有的方法內鍵入Adapter,再輸入其范圍內的一個關鍵字以打開智能感知,你應該也可看到一個Connection屬性,這意味著我們可以在業務邏輯層通過編程對連接設置進行讀取或賦值操作.

第三步:考察與Command相關的屬性

  一個TableAdapter有一個主查詢(main query),主查詢默認情況下會自動生成INSERT, UPDATE,以及DELETE statements.該主查詢的INSERT, UPDATE,DELETE statements在TableAdapter的代碼裡通過Adapter屬性以一個ADO.NET data adapter object(ADO.NET數據適配器對象)的形式來執行.
由於我們的教程使用的SqlClient provider,因此Adapter屬性為SqlDataAdapter類型.

TableAdapter的Adapter屬性有3個SqlCommand類型的屬性,分別用來發出INSERT, UPDATE,DELETE statements:

.InsertCommand
.UpdateCommand
.DeleteCommand

  一個SqlCommand對象負責向數據庫發出某個具體的查詢,並有相應的屬性,比如:CommandText屬性包含了要執行的ad-hoc SQL statement或存儲過程;Parameters屬性是一個SqlParameter對象集。就像我們在第一章《 創建一個數據訪問層》探討的一樣,這些command對象可以通過屬性窗口進行用戶定制.

  除了主查詢外,TableAdapter還包含一系列的方法,當調用這些方法時,就向數據庫發出具體的命令.主查詢的command對象以及其它所有方法使用的command對象都保存在TableAdapter的CommandCollection屬性裡.

我們花點時間看看Northwind數據集裡的ProductsTableAdapter生成的有關這2個屬性及其支持的成員變量、方法:

private System.Data.SqlClient.SqlDataAdapter _adapter;

private void InitAdapter() {
 this._adapter = new System.Data.SqlClient.SqlDataAdapter();
 
 ... Code that creates the InsertCommand, UpdateCommand, ...
 ... and DeleteCommand instances - omitted for brevity ...
}

private System.Data.SqlClient.SqlDataAdapter Adapter {
 get {
 if ((this._adapter == null)) {
  this.InitAdapter();
 }
 return this._adapter;
 }
}

private System.Data.SqlClient.SqlCommand[] _commandCollection;

private void InitCommandCollection() {
 this._commandCollection = new System.Data.SqlClient.SqlCommand[9];

 ... Code that creates the command objects for the main query and the ...
 ... ProductsTableAdapters other eight methods - omitted for brevity ...
}

protected System.Data.SqlClient.SqlCommand[] CommandCollection {
 get {
 if ((this._commandCollection == null)) {
  this.InitCommandCollection();
 }
 return this._commandCollection;
 }
}

  Adapter 和 CommandCollection屬性的代碼與Connection屬性的代碼很相似.這些屬性的get模塊一開始檢測相應的成員變量是否為null,如果是,那麼調用一個方法,以創建這個成員變量的一個實例,然後對與command相關的屬性進行賦值.

第四步:訪問與Command相關的設置

  理想狀態下,命令級(command-level)的信息應該封裝在數據訪問層。當然,我們也可以通過一個部分類來對其進行擴展,就像數據庫連接級(connection-level)的設置一樣.

  由於TableAdapter只有一個單一的Connection屬性,所以那些用於擴展數據庫連接級設置的代碼是非常直觀易懂的.而如果要修改命令級的設置的話要復雜一些,這是因為TableAdapter包含了多個command對象——InsertCommand, UpdateCommand,DeleteCommand, 以及CommandCollection 屬性包含的數量不等的command對象.當更新命令級的設置時,這些設置需要告知所有的這些command對象.

  比如,假如在一個TableAdapter裡某些查詢需要花很長的時間才能執行.當使用該TableAdapter來執行其中的一個查詢時,我們可能希望增大command對象的CommandTimeout屬性的值.該屬性指定了等待命令執行的時間,默認為30秒.

  想要從業務邏輯層來調整CommandTimeout屬性的話,可以用我們在第二步裡創建的部分類向ProductsDataTable添加一個public類型的方法,如下:(在ProductsTableAdapter.ConnectionAndCommandSettings.cs文件添加):

public void SetCommandTimeout(int timeout)
{
 if (this.Adapter.InsertCommand != null)
 this.Adapter.InsertCommand.CommandTimeout = timeout;

 if (this.Adapter.DeleteCommand != null)
 this.Adapter.DeleteCommand.CommandTimeout = timeout;

 if (this.Adapter.UpdateCommand != null)
 this.Adapter.UpdateCommand.CommandTimeout = timeout;

 for (int i = 0; i < this.CommandCollection.Length; i++)
 if (this.CommandCollection[i] != null)
  this.CommandCollection[i].CommandTimeout = timeout;
}

  我們可以從BLL層或表現層調用該方法,以設置某個TableAdapter實例發出的所有命令的command timeout值.

  注意:Adapter 和 CommandCollection屬性被標記為private,這就意味著只能在TableAdapter內部對其訪問.於Connection屬性不同,我們不能改變其訪問權限配置.因此,如果你想對其進行擴展以便從體系的其它層對其進行訪問的話,像上面討論的那樣,我們必須使用部分類來提供一個public類型的方法或屬性,對這些標記為private的命令對象進行讀寫操作.

結語:

  TableAdapters將數據訪問等細節進行的封裝,因此我們使用TableAdapters的時候,不用關心手寫ADO.NET代碼以連接數據庫、發出命令、用檢索的數據填充DataTable等.因為它已經自動生成了這些代碼.

  但是在某些時候,我們需要定制這些ADO.NET細節,比如改變連接字符串或默認的command timeout和connection timeout的值.TableAdapter自動生成了Connection, Adapter,以及CommandCollection屬性,但是默認情況下這些屬性要麼標記為internal要麼為private.我們可以對這些內部信息進行擴展,方法就是使用部分類,在部分類裡使用標記為public的方法或屬性.另外,對TableAdapter的Connection屬性,我們可以通過TableAdapter的ConnectionModifier屬性來改變其訪問權限.

  祝編程快樂!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數據教程》,希望對大家的學習ASP.NET有所幫助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved