使用計算資料行 (C#)

作者 :Scott Mitchell

下載 PDF

建立資料庫數據表時,Microsoft SQL Server 可讓您定義計算數據行,其值是從通常參考相同資料庫記錄中其他值的表達式計算而來。 這類值在資料庫中是只讀的,在處理 TableAdapters 時需要特殊考慮。 在本教學課程中,我們將瞭解如何滿足計算數據行所造成的挑戰。

簡介

Microsoft SQL Server 允許計算數據行,這是從表達式計算其值的數據行,通常參考相同數據表中其他數據行的值。 例如,時間追蹤數據模型可能有一 ServiceLog 個名為的數據表,其數據行包括 ServicePerformedEmployeeIDRateDuration等等。 雖然每個服務專案的到期金額 (乘以持續時間) 可透過網頁或其他程序設計介面來計算,但可能會方便在回報這項信息的數據表中包含 ServiceLog 數據 AmountDue 行。 此數據行可以建立為一般數據行,但每當 RateDuration 數據行值變更時,都必須加以更新。 更好的方法是使用表示式Rate * Duration,讓數據AmountDue行成為計算數據行。 這麼做會導致 SQL Server 在查詢中參考時自動計算AmountDue數據行值。

由於計算數據行的值是由表達式所決定,因此這類數據行是唯讀的,因此不能在 或 UPDATE 語句中INSERT指派值。 不過,當計算數據行是使用臨機操作 SQL 語句之 TableAdapter 主要查詢的一部分時,它們會自動包含在自動產生的 INSERTUPDATE 語句中。 因此,必須更新 TableAdapter 和 INSERTUPDATE 查詢和InsertCommandUpdateCommand屬性,才能移除任何計算數據行的參考。

搭配使用特定 SQL 語句的 TableAdapter 使用計算數據行的其中一項挑戰是,每當 TableAdapter 設定精靈完成時,就會自動重新產生 TableAdapter 和INSERTUPDATE查詢。 因此,如果重新執行精靈,則手動從 INSERTUPDATE 查詢中移除的計算數據行將會重新出現。 雖然使用預存程式的 TableAdapters 不會受到這種嚴重性影響,但它們確實有自己的 quirks,我們會在步驟 3 中加以解決。

在本教學課程中,我們會將計算數據行新增至 Northwind 資料庫中的 Suppliers 數據表,然後建立對應的 TableAdapter 來處理此數據表及其計算數據行。 我們將讓 TableAdapter 使用預存程式,而不是臨機操作 SQL 語句,以便在使用 TableAdapter 組態精靈時不會遺失我們的自定義。

讓我們開始吧!

步驟 1:將計算數據行新增至Suppliers數據表

Northwind 資料庫沒有任何計算數據行,因此我們必須自行新增計算數據行。 在本教學課程中,讓我們將計算數據行新增至 Suppliers 名為 FullContactName 的數據表,以傳回聯繫人的名稱、標題,以及他們所使用的公司,格式如下: ContactName (ContactTitleCompanyName) 。 此計算數據行可能會在顯示供應商的相關信息時用於報表中。

從開啟 Suppliers 數據表定義開始,方法是以滑鼠右鍵按兩下 Suppliers [伺服器總管] 中的數據表,然後從操作功能表選擇 [開啟數據表定義]。 這會顯示數據表的數據行及其屬性,例如其數據類型、是否允許 NULL 等等。 若要加入計算數據行,請先在數據表定義中輸入數據行的名稱。 接下來,在 [數據行 屬性視窗 (的 [計算數據行規格] 區段底下的 [ (Formula) ] 文本框中輸入表達式,請參閱圖 1) 。 將計算資料列 FullContactName 命名為 ,並使用下列運算式:

ContactName + ' (' + CASE WHEN ContactTitle IS NOT NULL THEN 
    ContactTitle + ', ' ELSE '' END + CompanyName + ')'

請注意,字串可以使用 運算符串連在 SQL + 中。 語句 CASE 可以像傳統程式設計語言中的條件一樣使用。 在上述表達式中, CASE 語句可以讀取為:如果 ContactTitle 不是 NULL ,則輸出 ContactTitle 以逗號串連的值,否則不會發出任何內容。 如需語句有用性 CASE 的詳細資訊,請參閱 SQL CASE 語句

注意

我們可以改用 ,而不是在這裡使用 CASEISNULL(ContactTitle, '')語句。 ISNULL(checkExpression, replacementValue) 如果 checkExpression 不是 NULL,則會傳回 checkExpression,否則會傳回 replacementValueISNULL雖然 或 CASE 可在這個實例中運作,但有更複雜的案例,語句的CASE彈性無法比對。ISNULL

新增此計算數據行之後,您的畫面看起來應該像圖 1 中的螢幕快照。

將名為 FullContactName 的計算數據行新增至供應商數據表

圖 1:將名為 FullContactName 的計算資料行新增至 Suppliers 數據表 (按兩下即可檢視完整大小的影像)

命名計算數據行並輸入其表達式之後,單擊工具列中的 [儲存] 圖示、按 Ctrl+S,或移至 [檔案] 功能表,然後選擇 [儲存 Suppliers] 來儲存數據表的變更。

儲存數據表應該會重新整理伺服器總管,包括數據表數據行 Suppliers 清單中的 Just-added 資料行。 此外,輸入 (公式) 文本框的表達式會自動調整為等價的表達式,以去除不必要的空格符、以括弧括住數據行名稱 ([]) ,並包含括弧以更明確地顯示作業順序:

(((([ContactName]+' (')+case when [ContactTitle] IS NOT NULL 
    then [ContactTitle]+', ' else '' end)+[CompanyName])+')')

如需 Microsoft SQL Server 中計算數據行的詳細資訊,請參閱技術檔。 另請參閱 如何:為建立計算 數據行的逐步解說指定計算數據行。

注意

根據預設,計算數據行不會實際儲存在數據表中,而是會在每次在查詢中參考時重新計算。 不過,您可以核取 [Is Persisted] 複選框,指示 SQL Server 實際將計算數據行儲存在數據表中。 這麼做允許在計算數據行上建立索引,這可以改善在其 子句中使用 WHERE 計算數據行值的查詢效能。 如需詳細資訊,請參閱 在計算數據行上建立索引

步驟 2:檢視計算數據行的值

在開始處理數據存取層之前,讓我們花一分鐘的時間檢視 FullContactName 這些值。 從 [伺服器總管] 中,以滑鼠右鍵按兩下 Suppliers 數據表名稱,然後從操作選單選擇 [新增查詢]。 這會顯示 [查詢] 視窗,提示我們選擇要包含在查詢中的數據表。 Suppliers新增數據表,然後按兩下 [關閉]。 接下來,檢查 CompanyName供應商數據表中的、 ContactNameContactTitleFullContactName 資料行。 最後,按兩下工具列中的紅色驚嘆號圖示,以執行查詢並檢視結果。

如圖 2 所示,結果包括 FullContactName,其中會使用 ldquo 格式列出 CompanyNameContactName和資料 ContactTitle 行;ContactName (ContactTitleCompanyName) 。

FullContactName 會使用 ContactName (ContactTitle、CompanyName) 格式

圖 2FullContactName 使用格式 ContactName (ContactTitleCompanyName) (按鍵即可檢視完整大小的影像)

步驟 3:將 新增SuppliersTableAdapter至數據存取層

若要使用應用程式中的供應商資訊,我們必須先在 DAL 中建立 TableAdapter 和 DataTable。 在理想情況下,這可以使用先前教學課程中所檢查的相同直接步驟來完成。 不過,使用計算數據行引進了一些值得討論的一些建議。

如果您使用使用臨機操作 SQL 語句的 TableAdapter,只要透過 TableAdapter 組態精靈將計算數據行包含在 TableAdapter 的主要查詢中即可。 不過,這會自動產生 INSERTUPDATE 包含計算數據行的語句。 如果您嘗試執行其中一個方法, SqlException 則含有訊息的 ,無法修改 ColumnName 數據行,因為它是計算數據行,或是會擲回 UNION 運算子的結果。 INSERT雖然 和 UPDATE 語句可以透過 TableAdapter 和 InsertCommandUpdateCommand 屬性手動調整,但只要重新執行 TableAdapter 組態精靈,這些自定義就會遺失。

由於使用臨機操作 SQL 語句的 TableAdapters 的不相依性,建議您在處理計算數據行時使用預存程式。 如果您使用現有的預存程式,只要設定 TableAdapter,如 針對 Typed DataSet s TableAdapters 使用現有預存程式 教學課程中所述。 不過,如果您有 TableAdapter 精靈為您建立預存程式,請務必一開始省略主查詢中的任何計算數據行。 如果您在主要查詢中包含計算數據行,TableAdapter 組態精靈會在完成時通知您,它無法建立對應的預存程式。 簡單地說,我們需要一開始使用不含計算數據行的主要查詢來設定 TableAdapter,然後手動更新對應的預存程式和 TableAdapter, SelectCommand 以包含計算數據行。 此方法類似於 將 TableAdapter 更新為使用JOIN教學 課程中使用的方法。

在本教學課程中,讓我們新增 TableAdapter,並自動為我們建立預存程式。 因此,我們一開始必須省略 FullContactName 主查詢中的計算數據行。

從開啟資料夾中的 NorthwindWithSprocs~/App_Code/DAL DataSet 開始。 在 Designer 中按兩下滑鼠右鍵,然後從操作選單中選擇新增 TableAdapter。 這會啟動 TableAdapter 組態精靈。 指定要從 Web.config) 查詢 (NORTHWNDConnectionString 數據的資料庫,然後按 [下一步]。 因為我們尚未建立任何預存程式來查詢或修改 Suppliers 數據表,請選取 [建立新的預存程式] 選項,讓精靈為我們建立預存程式,然後按 [下一步]。

選擇 [建立新的預存程式] 選項

圖 3:選擇 [建立新的預存程式] 選項 (按兩下以檢視完整大小的映像)

後續步驟會提示我們進行主要查詢。 輸入下列查詢,其會傳回每個供應商的 SupplierIDCompanyNameContactName、 和 ContactTitle 數據行。 請注意,此查詢會刻意省略計算數據行 (FullContactName) ;我們會更新對應的預存程式,以在步驟 4 中包含此數據行。

SELECT SupplierID, CompanyName, ContactName, ContactTitle
FROM Suppliers

輸入主要查詢並按兩下一步之後,精靈可讓我們命名其將產生的四個預存程式。 將這些預存程式 Suppliers_Select命名為 、 Suppliers_InsertSuppliers_UpdateSuppliers_Delete,如圖 4 所示。

自訂自動產生的預存程序名稱

圖 4:自定義自動產生的預存程式名稱, (按單擊即可檢視完整大小的映像)

下一個精靈步驟可讓我們命名 TableAdapter 的方法,並指定用來存取和更新數據的模式。 讓所有三個複選框保持核取狀態,但將 GetData 方法重新命名為 GetSuppliers。 按一下 [完成] 以完成精靈。

將 GetData 方法重新命名為 GetSuppliers

圖 5:將 GetData 方法重新命名為 GetSuppliers (按兩下即可檢視完整大小的影像)

單擊 [完成] 時,精靈會建立四個預存程式,並將 TableAdapter 和對應的 DataTable 新增至具類型的數據集。

步驟 4:在 TableAdapter s Main Query 中包含計算數據行

我們現在需要更新在步驟 3 中建立的 TableAdapter 和 DataTable,以包含 FullContactName 計算數據行。 這包含兩個步驟:

  1. 更新 Suppliers_Select 預存程式以傳回 FullContactName 計算數據行,以及
  2. 更新 DataTable 以包含對應的 FullContactName 數據行。

從流覽至 [伺服器總管] 並向下切入至 [預存程式] 資料夾開始。 Suppliers_Select開啟預存程式,並更新SELECT查詢以包含FullContactName計算資料列:

SELECT SupplierID, CompanyName, ContactName, ContactTitle, FullContactName
FROM Suppliers

單擊工具列中的 [儲存] 圖示、按 Ctrl+S,或從 [檔案] 功能表選擇 [儲存 Suppliers_Select ] 選項,以儲存預存程序的變更。

接下來,返回 DataSet Designer,以滑鼠右鍵按兩下 SuppliersTableAdapter,然後從操作選單選擇 [設定]。 請注意,數據 Suppliers_Select 行現在會在其 [數據行] 集合中包含數據 FullContactName 行。

執行 TableAdapter 的設定精靈來更新 DataTable s 數據行

圖 6:執行 TableAdapter 的設定精靈來更新 DataTable s 數據行 (按兩下即可檢視完整大小的映像)

按一下 [完成] 以完成精靈。 這會自動將對應的資料列新增至 SuppliersDataTable。 TableAdapter 精靈很聰明,可偵測 FullContactName 數據行是計算數據行,因此是只讀的。 因此,它會將資料行的 ReadOnly 屬性設定為 true。 若要確認這一點,請從 SuppliersDataTable 選取數據行,然後移至 屬性視窗 (請參閱圖 7) 。 請注意,也會據此設定數據FullContactName行和DataTypeMaxLength屬性。

FullContactName 數據行標示為唯讀

圖 7:數據 FullContactName 行標示為 Read-Only (按兩下即可檢視完整大小的影像)

步驟 5:將方法新增GetSupplierBySupplierID至 TableAdapter

在本教學課程中,我們將建立 ASP.NET 頁面,以在可更新的方格中顯示供應商。 在過去教學課程中,我們已從商業規則層更新單一記錄,方法是從 DAL 擷取該特定記錄做為強型別 DataTable、更新其屬性,然後將更新的 DataTable 傳回 DAL,以將變更傳播至資料庫。 若要完成此第一個步驟 - 從 DAL 擷取要更新的記錄 - 我們必須先將方法新增 GetSupplierBySupplierID(supplierID) 至 DAL。

以滑鼠右鍵按兩下 SuppliersTableAdapter [資料集設計] 中的 ,然後從操作選單選擇 [新增查詢] 選項。 如同我們在步驟 3 中所做的一樣,請選取 [建立新的預存程式] 選項,讓精靈為我們產生新的預存程式, (請參閱圖 3,以取得此精靈步驟) 的螢幕快照。 因為這個方法會傳回具有多個數據行的記錄,所以表示我們想要使用 SQL 查詢,這是一個 SELECT,它會傳回數據列,然後按 [下一步]。

選擇傳回數據列選項的SELECT

圖 8:選擇 SELECT 以傳回數據列選項 (按一下以檢視完整大小的影像)

後續步驟會提示我們查詢用於這個方法。 輸入下列命令,其會傳回與主要查詢相同的數據欄位,但針對特定供應商。

SELECT SupplierID, CompanyName, ContactName, ContactTitle, FullContactName
FROM Suppliers
WHERE SupplierID = @SupplierID

下一個畫面會要求我們命名將自動產生的預存程式。 將此預存程式 Suppliers_SelectBySupplierID 命名為 ,然後按 [下一步]。

將預存程式命名為Suppliers_SelectBySupplierID

圖 9:將預存程式 Suppliers_SelectBySupplierID 命名 (按兩下即可檢視完整大小的影像)

最後,精靈會提示我們輸入用於 TableAdapter 的數據存取模式和方法名稱。 讓這兩個複選框保持核取狀態,但分別將 FillByGetDataBy 方法重新命名為 FillBySupplierIDGetSupplierBySupplierID

將 TableAdapter 方法命名為 FillBySupplierID 和 GetSupplierBySupplierID

圖 10:命名 TableAdapter 方法和 FillBySupplierIDGetSupplierBySupplierID (按兩下即可檢視完整大小的影像)

按一下 [完成] 以完成精靈。

步驟 6:建立商業規則層

在建立使用步驟 1 中所建立計算數據行的 ASP.NET 頁面之前,我們必須先在 BLL 中新增對應的方法。 我們將在步驟 7 中建立 ASP.NET 頁面,可讓用戶檢視和編輯供應商。 因此,我們需要 BLL 至少提供一種方法,以取得所有供應商,另一個方法來更新特定供應商。

在資料夾中建立名為 SuppliersBLLWithSprocs~/App_Code/BLL 的新類別檔案,並新增下列程序代碼:

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;
using NorthwindWithSprocsTableAdapters;
[System.ComponentModel.DataObject]
public class SuppliersBLLWithSprocs
{
    private SuppliersTableAdapter _suppliersAdapter = null;
    protected SuppliersTableAdapter Adapter
    {
        get
        {
            if (_suppliersAdapter == null)
                _suppliersAdapter = new SuppliersTableAdapter();
            return _suppliersAdapter;
        }
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Select, true)]
    public NorthwindWithSprocs.SuppliersDataTable GetSuppliers()
    {
        return Adapter.GetSuppliers();
    }
    [System.ComponentModel.DataObjectMethodAttribute
        (System.ComponentModel.DataObjectMethodType.Update, true)]
    public bool UpdateSupplier(string companyName, string contactName, 
        string contactTitle, int supplierID)
    {
        NorthwindWithSprocs.SuppliersDataTable suppliers = 
            Adapter.GetSupplierBySupplierID(supplierID);
        if (suppliers.Count == 0)
            // no matching record found, return false
            return false;
        NorthwindWithSprocs.SuppliersRow supplier = suppliers[0];
        supplier.CompanyName = companyName;
        if (contactName == null) 
            supplier.SetContactNameNull(); 
        else 
            supplier.ContactName = contactName;
        if (contactTitle == null) 
            supplier.SetContactTitleNull(); 
        else 
            supplier.ContactTitle = contactTitle;
        // Update the product record
        int rowsAffected = Adapter.Update(supplier);
        // Return true if precisely one row was updated, otherwise false
        return rowsAffected == 1;
    }
}

與其他 BLL 類別一樣,SuppliersBLLWithSprocs有一個屬性會傳回 類別的SuppliersTableAdapter實例,以及兩publicprotectedAdapter方法: GetSuppliersUpdateSupplier。 方法會GetSuppliers呼叫 ,並傳回資料存取層中對應GetSupplier方法傳回SuppliersDataTable的 。 方法 UpdateSupplier 會擷取透過呼叫 DAL s GetSupplierBySupplierID(supplierID) 方法更新之特定供應商的相關信息。 然後,它會更新 CategoryNameContactNameContactTitle 屬性,並藉由呼叫 Data Access Layer s Update 方法,傳入修改 SuppliersRow 的物件,將這些變更認可至資料庫。

注意

SupplierID除了和 CompanyName之外,供應商數據表中的所有數據行都允許NULL值。 因此,如果傳入contactName或參數是null我們需要分別使用 SetContactNameNull 和方法,將對應的 ContactNameContactTitleSetContactTitleNull 屬性設定為NULL資料庫contactTitle值。

步驟 7:使用呈現層中的計算數據行

將計算數據行新增至 Suppliers 數據表,並據以更新 DAL 和 BLL 之後,我們已準備好建置可與計算數據行搭配 FullContactName 運作的 ASP.NET 頁面。 從開啟資料夾中的頁面AdvancedDAL開始,ComputedColumns.aspx並將 GridView 從 [工具箱] 拖曳至 Designer。 將 GridView 的 ID 屬性設定為 Suppliers ,並從其智慧標記將它系結至名為 SuppliersDataSource的新 ObjectDataSource。 將 ObjectDataSource 設定為使用 SuppliersBLLWithSprocs 我們在步驟 6 中新增的 類別,然後按 [下一步]。

將 ObjectDataSource 設定為使用 SuppliersBLLWithSprocs 類別

圖 11:將 ObjectDataSource 設定為使用 SuppliersBLLWithSprocs 類別 (按兩下即可檢視完整大小的影像)

類別中 SuppliersBLLWithSprocs 只有兩個定義的方法: GetSuppliersUpdateSupplier。 請確定這兩種方法分別在 SELECT 和 UPDATE 索引標籤中指定,然後按兩下 [完成] 以完成 ObjectDataSource 的設定。

完成 [數據源設定精靈] 之後,Visual Studio 會為每個傳回的數據欄位新增 BoundField。 SupplierID拿掉 BoundField,並將 、ContactNameContactTitleFullContactName BoundFields 的屬性CompanyName分別變更HeaderText為公司、聯繫人名稱、標題和完整聯繫人名稱。 從智慧標記中,核取 [啟用編輯] 複選框,以開啟 GridView 的內建編輯功能。

除了將 BoundFields 新增至 GridView 之外,[數據源精靈] 完成也會讓 Visual Studio 將 ObjectDataSource s OldValuesParameterFormatString 屬性設定為 original_{0}。 將這個設定還原回預設值 {0}

對 GridView 和 ObjectDataSource 進行這些編輯之後,其宣告式標記看起來應該如下所示:

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="CompanyName" 
            HeaderText="Company" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="ContactName" 
            HeaderText="Contact Name" 
            SortExpression="ContactName" />
        <asp:BoundField DataField="ContactTitle" 
            HeaderText="Title" 
            SortExpression="ContactTitle" />
        <asp:BoundField DataField="FullContactName" 
            HeaderText="Full Contact Name"
            SortExpression="FullContactName" 
            ReadOnly="True" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLLWithSprocs" 
        UpdateMethod="UpdateSupplier">
    <UpdateParameters>
        <asp:Parameter Name="companyName" Type="String" />
        <asp:Parameter Name="contactName" Type="String" />
        <asp:Parameter Name="contactTitle" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

接下來,透過瀏覽器瀏覽此頁面。 如圖 12 所示,每個供應商都會列在包含資料 FullContactName 行的方格中,其值只是其他三個格式化為 ContactName (ContactTitle的數據行串連, CompanyName) 。

每個供應商都會列在方格中

圖 12:每個供應商都會列在方格 (按兩下以檢視完整大小的影像)

按下特定供應商的 [編輯] 按鈕會導致回傳,並在其編輯介面中呈現該數據列, (請參閱圖 13) 。 前三個數據行會呈現在其預設編輯介面中 - TextBox 控件,其 Text 屬性設定為數據欄位的值。 不過,數據 FullContactName 行會維持為文字。 在 [數據源組態精靈] 完成時將 BoundFields 新增至 GridView 時,BoundField 的 ReadOnly 屬性會設定為 trueFullContactName因為 中的SuppliersDataTable對應FullContactName數據行已將其 ReadOnly 屬性設定為 true。 如步驟 4 所述, FullContactName s ReadOnly 屬性已設定為 true ,因為 TableAdapter 偵測到數據行是計算數據行。

FullContactName 數據行不可編輯

圖 13:數據 FullContactName 行不可編輯 (按鍵即可檢視完整大小的影像)

繼續並更新一或多個可編輯數據行的值,然後按兩下 [更新]。 請注意 s 值如何 FullContactName 自動更新以反映變更。

注意

GridView 目前會針對可編輯的欄位使用 BoundFields,導致預設編輯介面。 CompanyName因為需要欄位,所以它應該轉換成包含 RequiredFieldValidator 的 TemplateField。 我將此保留為感興趣的讀者練習。 如需將 BoundField 轉換為 TemplateField 及新增驗證控件的逐步指示,請參閱 將驗證控件新增至編輯和插入介面 教學課程。

摘要

定義數據表的架構時,Microsoft SQL Server 允許包含計算數據行。 這些數據行的值是從表達式計算而來,通常參考相同記錄中其他數據行的值。 由於計算數據行的值是以表達式為基礎,因此它們是唯讀的,而且無法在 或 UPDATE 語句中INSERT指派值。 這會在 TableAdapter 的主要查詢中使用計算數據行,嘗試自動產生對應的 INSERTUPDATEDELETE 語句時,這會造成挑戰。

在本教學課程中,我們討論了規避計算數據行所造成挑戰的技術。 特別是,我們使用 TableAdapter 中的預存程式來克服使用臨機操作 SQL 語句的 TableAdapters 固有的不相依性。 當 TableAdapter 精靈建立新的預存程式時,請務必讓主要查詢一開始省略任何計算數據行,因為它們的存在會防止產生數據修改預存程式。 一開始設定 TableAdapter 之後,可以重新調整其 SelectCommand 預存程式以包含任何計算數據行。

快樂的程序設計!

關於作者

Scott Mitchell 是 1998 年以來,1998 年與 Microsoft Web 技術合作的 篇 ASP/ASP.NET 書籍和 4GuysFromRolla.com 作者。 Scott 是獨立的顧問、訓練者和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET

特別感謝

本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是「格氏」和「Teresa Murphy」。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。