認識并測量Typed DataSet Truly 2005-08-05 下載本文的源碼(C#) - 17k 下載本文的源碼(VB) - 15k 簡介 強類型DataSet 強類型DataSet是從DataSet繼承的定制對象,它可以通過其顯露的屬性(properties)來對封裝數(shù)據(jù)進行強類型的訪問。 強類型DataSet避免了字段的晚綁定。強類型DataSet提供了強類型的訪問器,因為避免了到一個集合中查找列名或表名,訪問時更快。 除了能夠提高運行時的性能,強類型DataSet還提供了類型檢查,并且在設(shè)計時可以通過自定義字段名對字段智能感知。 在實例化和封送的性能上,強類型的DataSet和普通的DataSet大致相當。主要的性能優(yōu)勢在于客戶端可以直接訪問方法和屬性而毋須通過集合。 創(chuàng)建Typed DataSet 這里借用MSDN的一篇文章http://support.microsoft.com/default.aspx?scid=kb;en-us;320714 簡單的說就是在項目上點右鍵—》添加新項-》數(shù)據(jù)集-》取名dsProducts,然后在從服務(wù)器資源管理器中將sqlserver展開找到Northwind的Alphabetical list of products視圖拖入dsProducts的設(shè)計窗口-》保存。 性能測量 好啦,下面我們對通過兩個簡單的頁面來對常規(guī)DataSet和Typed DataSet進行一下性能比較 完整源碼(NormalDataSet.aspx) | <%@ Page language="c#" Codebehind="NormalDataSet.aspx.cs" AutoEventWireup="false" Inherits="STD.NormalDataSet" %>
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en" >
<HTML><HEAD><TITLE>NormalDataSet</TITLE><META name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"><META name="CODE_LANGUAGE" content="C#"><META name=vs_defaultClientScript content="JavaScript"><META name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"></HEAD><BODY ms_positioning="GridLayout"><FORM id="Form1" method="post" runat="server"><ASP:LABEL id=Label1 style="Z-INDEX: 101; LEFT: 250px; POSITION: absolute; TOP: 250px" runat="server" /></FORM></BODY>
</HTML>
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="NormalDataSet.aspx.vb" Inherits="STDvb.NormalDataSet"%>
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
<HTML><HEAD><TITLE>NormalDataSet</TITLE><META name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"><META name="CODE_LANGUAGE" content="Visual Basic .NET 7.1"><META name=vs_defaultClientScript content="JavaScript"><META name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"></HEAD><BODY ms_positioning="GridLayout"><FORM id="Form1" method="post" runat="server"><ASP:LABEL id=Label1 style="Z-INDEX: 101; LEFT: 250px; POSITION: absolute; TOP: 250px" runat="server" /></FORM></BODY>
</HTML>
| | C# | VB | 隱藏代碼 | ? |
完整源碼(NormalDataSet.aspx.cs/vb) | using System;
using System.Data;
using System.Data.SqlClient;
namespace STD
{/// <SUMMARY>/// WebForm2 的摘要說明。/// </SUMMARY>public class NormalDataSet : System.Web.UI.Page{protected System.Web.UI.WebControls.Label Label1;private void Page_Load(object sender, System.EventArgs e){SqlConnection cn = new SqlConnection("server=localhost;uid=sa;pwd=;database=northwind");SqlCommand cmd = new SqlCommand("select * from [Alphabetical list of products]", cn);SqlDataAdapter da = new SqlDataAdapter(cmd);DataSet tds = new DataSet();da.Fill(tds);long begin = DateTime.Now.Ticks;// 放大性能差異for(int k =0;k<10000;k++){for(int i = 0,j = tds.Tables[0].Rows.Count;i<J;i++){label1.text = tds.Tables[0].Rows[i]["ProductName"].ToString();}}long end = DateTime.Now.Ticks;response.write("Total Time(ms): " + (end- begin));}#region web 窗體設(shè)計器生成的代碼override protected void oninit(eventargs e){//// CODEGEN: 該調(diào)用是 asp.net web 窗體設(shè)計器所必需的。//initializecomponent();base.oninit(e);}/// <SUMMARY>/// 設(shè)計器支持所需的方法 - 不要使用代碼編輯器修改/// 此方法的內(nèi)容。/// </SUMMARY>private void InitializeComponent(){ this.Load += new System.EventHandler(this.Page_Load);}#endregion}
}
Imports System.Data.SqlClient
Public Class NormalDataSetInherits System.Web.UI.Page#Region " Web 窗體設(shè)計器生成的代碼 "'該調(diào)用是 Web 窗體設(shè)計器所必需的。<SYSTEM.DIAGNOSTICS.DEBUGGERSTEPTHROUGH()> Private Sub InitializeComponent()End SubProtected WithEvents Label1 As System.Web.UI.WebControls.Label'注意: 以下占位符聲明是 Web 窗體設(shè)計器所必需的。'不要刪除或移動它。Private designerPlaceholderDeclaration As System.ObjectPrivate Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init'CODEGEN: 此方法調(diào)用是 Web 窗體設(shè)計器所必需的'不要使用代碼編輯器修改它。InitializeComponent()End Sub#End RegionPrivate Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadDim cn As SqlConnection = New SqlConnection("server=localhost;uid=sa;pwd=;database=northwind")Dim cmd As SqlCommand = New SqlCommand("select * from [Alphabetical list of products]", cn)Dim da As SqlDataAdapter = New SqlDataAdapter(cmd)Dim tds As DataSet = New DataSetda.Fill(tds)Dim lngBegin As Long = DateTime.Now.Ticks' 放大性能差異Dim k, i As IntegerFor k = 0 To 10000For i = 0 To tds.Tables(0).Rows.Count - 1Label1.Text = tds.Tables(0).Rows(i)("ProductName").ToString()NextNextDim lngEnd As Long = DateTime.Now.TicksResponse.Write("Total Time(ms): " & (lngEnd - lngBegin))End SubEnd Class | | C# | VB | 隱藏代碼 | ? |
完整源碼(TypedDataSet.aspx) | <%@ Page language="c#" Codebehind="TypedDataSet.aspx.cs" AutoEventWireup="false" Inherits="STD.TypedDataSet" %>
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en" >
<HTML><HEAD><TITLE>TypedDataSet</TITLE><META name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"><META name="CODE_LANGUAGE" content="C#"><META name=vs_defaultClientScript content="JavaScript"><META name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"></HEAD><BODY ms_positioning="GridLayout"><FORM id="Form1" method="post" runat="server"><ASP:LABEL id=Label1 style="Z-INDEX: 101; LEFT: 250px; POSITION: absolute; TOP: 250px" runat="server" /></FORM></BODY>
</HTML>
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="TypedDataSet.aspx.vb" Inherits="STDvb.TypedDataSet"%>
<!DOCTYPE html public "-//w3c//dtd html 4.0 transitional//en">
<HTML><HEAD><TITLE>TypedDataSet</TITLE><META name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"><META name="CODE_LANGUAGE" content="Visual Basic .NET 7.1"><META name=vs_defaultClientScript content="JavaScript"><META name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"></HEAD><BODY ms_positioning="GridLayout"><FORM id="Form1" method="post" runat="server"><ASP:LABEL id=Label1 style="Z-INDEX: 101; LEFT: 250px; POSITION: absolute; TOP: 250px" runat="server" /></FORM></BODY>
</HTML>
| | C# | VB | 隱藏代碼 | ? |
完整源碼(TypedDataSet.aspx.cs/TypedDataSet.aspx.vb) | using System;
using System.Data.SqlClient;namespace STD
{/// <SUMMARY>/// WebForm1 的摘要說明。/// </SUMMARY>public class TypedDataSet : System.Web.UI.Page{protected System.Web.UI.WebControls.Label Label1;private void Page_Load(object sender, System.EventArgs e){SqlConnection cn = new SqlConnection("server=.;uid=sa;pwd=;database=northwind");SqlCommand cmd = new SqlCommand("select * from [Alphabetical list of products]", cn);SqlDataAdapter da = new SqlDataAdapter(cmd);dsProducts tds = new dsProducts();da.Fill(tds, tds.Tables[0].TableName);long begin = DateTime.Now.Ticks;// 放大性能差異for(int k =0;k<10000;k++){for(int i = 0,j = tds.Alphabetical_list_of_products.Rows.Count;i<J;i++){label1.text = tds.Alphabetical_list_of_products[i].ProductName;}}long end = DateTime.Now.Ticks;response.write( end- begin);}#region web 窗體設(shè)計器生成的代碼override protected void oninit(eventargs e){//// CODEGEN: 該調(diào)用是 asp.net web 窗體設(shè)計器所必需的。//initializecomponent();base.oninit(e);}/// <SUMMARY>/// 設(shè)計器支持所需的方法 - 不要使用代碼編輯器修改/// 此方法的內(nèi)容。/// </SUMMARY>private void InitializeComponent(){ this.Load += new System.EventHandler(this.Page_Load);}#endregion}
}
Imports System.Data.SqlClient
Public Class TypedDataSetInherits System.Web.UI.Page
#Region " Web 窗體設(shè)計器生成的代碼 "'該調(diào)用是 Web 窗體設(shè)計器所必需的。<SYSTEM.DIAGNOSTICS.DEBUGGERSTEPTHROUGH()> Private Sub InitializeComponent()End SubProtected WithEvents Label1 As System.Web.UI.WebControls.Label'注意: 以下占位符聲明是 Web 窗體設(shè)計器所必需的。'不要刪除或移動它。Private designerPlaceholderDeclaration As System.ObjectPrivate Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init'CODEGEN: 此方法調(diào)用是 Web 窗體設(shè)計器所必需的'不要使用代碼編輯器修改它。InitializeComponent()End Sub#End RegionPrivate Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadDim cn As SqlConnection = New SqlConnection("server=localhost;uid=sa;pwd=;database=northwind")Dim cmd As SqlCommand = New SqlCommand("select * from [Alphabetical list of products]", cn)Dim da As SqlDataAdapter = New SqlDataAdapter(cmd)Dim tds As dsProducts = New dsProductsda.Fill(tds, tds.Tables(0).TableName)Dim lngBegin As Long = DateTime.Now.Ticks' 放大性能差異Dim k, i As IntegerFor k = 0 To 10000For i = 0 To tds.Alphabetical_list_of_products.Rows.Count - 1Label1.Text = tds.Alphabetical_list_of_products(i).ProductNameNextNextDim lngEnd As Long = DateTime.Now.TicksResponse.Write("Total Time(ms): " & (lngEnd - lngBegin))End SubEnd Class | | C# | VB | 隱藏代碼 | ? |
測試結(jié)果(受操作系統(tǒng),硬件環(huán)境,框架版本等影響,僅供參考) 注:以下結(jié)果是從頁面運行結(jié)果取10次數(shù)值所得 | 頁面 | 平均 | 最小 | | NormalDataSet.aspx(C#) | 4687500 | 4375000 | | NormalDataSet.aspx(VB) | 4687500 | 4687500 | | TypedDataSet.aspx(C#) | 2500000 | 2343750 | | TypedDataSet.aspx(VB) | 3437500 | 3281250 |
典型的ACT測試結(jié)果(只對C#進行了測試,vb的頁面請自行測試比較 | 屬性 測試類型: 動態(tài) 瀏覽器同時連接數(shù): 1 準備時間(秒): 測試持續(xù)時間: 00:00:05:00 測試迭代次數(shù): 586 生成的詳細測試結(jié)果: 是 摘要 請求總數(shù): 586 連接總數(shù): 586 每秒平均請求數(shù): 1.95 首字節(jié)平均響應(yīng)時間(毫秒): 510.41 末字節(jié)平均響應(yīng)時間(毫秒): 510.48 每次迭代末字節(jié)平均響應(yīng)時間(毫秒): 510.48 測試中的唯一請求數(shù): 1 唯一響應(yīng)代碼數(shù): 1 錯誤計數(shù) HTTP: DNS: 套接字: 其他網(wǎng)絡(luò)統(tǒng)計數(shù)據(jù) 平均帶寬(字節(jié)/秒): 2,730.95 發(fā)送字節(jié)數(shù)(字節(jié)): 147,234 接收字節(jié)數(shù)(字節(jié)): 672,050 發(fā)送字節(jié)平均速率(字節(jié)/秒): 490.78 接收字節(jié)平均速率(字節(jié)/秒): 2,240.17 連接錯誤數(shù): 發(fā)送錯誤數(shù): 接收錯誤數(shù): 超時錯誤數(shù): 響應(yīng)代碼 Response Code: 200 - 請求已成功完成。 計數(shù): 586 百分比(%): 100.00
屬性 測試類型: 動態(tài) 瀏覽器同時連接數(shù): 1 準備時間(秒): 測試持續(xù)時間: 00:00:05:00 測試迭代次數(shù): 1,124 生成的詳細測試結(jié)果: 是 摘要 請求總數(shù): 1,124 連接總數(shù): 1,124 每秒平均請求數(shù): 3.75 首字節(jié)平均響應(yīng)時間(毫秒): 265.19 末字節(jié)平均響應(yīng)時間(毫秒): 265.27 每次迭代末字節(jié)平均響應(yīng)時間(毫秒): 265.27 測試中的唯一請求數(shù): 1 唯一響應(yīng)代碼數(shù): 1 錯誤計數(shù) HTTP: DNS: 套接字: 其他網(wǎng)絡(luò)統(tǒng)計數(shù)據(jù) 平均帶寬(字節(jié)/秒): 6,819.44 發(fā)送字節(jié)數(shù)(字節(jié)): 291,956 接收字節(jié)數(shù)(字節(jié)): 1,753,876 發(fā)送字節(jié)平均速率(字節(jié)/秒): 973.19 接收字節(jié)平均速率(字節(jié)/秒): 5,846.25 連接錯誤數(shù): 發(fā)送錯誤數(shù): 接收錯誤數(shù): 超時錯誤數(shù): 響應(yīng)代碼 Response Code: 200 - 請求已成功完成。 計數(shù): 1,124 百分比(%): 100.00
| | Normal DataSet | Typed DataSet | 隱藏結(jié)果 | ? |
小結(jié) 現(xiàn)在,你應(yīng)該對Typed DataSet有一點了解了,您也明白了它的優(yōu)勢所在,剩下的就是您在架構(gòu)程序時的決策了。 有些朋友認為沒有必要使用Typed DataSet,因為帶來了更復雜的結(jié)構(gòu)和更多的代碼,也有一些朋友認為Typed DataSet的性能更差或者沒有改善。這里想說的就是:性能在某些環(huán)境下無關(guān)緊要,而且另一些環(huán)境下卻是產(chǎn)品的最重要特性。過早的優(yōu)化是一切問題的根源。但是,不重視效率也會導致同樣的結(jié)果。您是專業(yè)人士,是藝術(shù)家,是能工巧將。那么,您一定要知道事物的開銷。如果您不知道或即使您認為自己知道,也要經(jīng)常進行測量。 參考資料 J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman, Improving .NET Application Performance and Scalability,MSDN HOW TO: Create and Use a Typed DataSet by Using Visual C# .NET, MSDN |