天天看點

如何gridview綁定到數組上面,并設定超連結

</head>

<body>

    <form id="form1" runat="server">

    <div style="text-align: center">

        <br />

        <table cellpadding="0" cellspacing="0" style="width: 429px" bordercolor="#cccccc" bordercolordark="#cccccc" bordercolorlight="#ffffff">

            <tr>

                <td >

                    <table cellpadding="0" cellspacing="0" style="width: 429px">

                        <tr>

                            <td  style="height: 127px; text-align: center; width: 429px;">

                                 <asp:GridView ID="GridView1" runat="server" AllowPaging="True" OnPageIndexChanging="GridView1_PageIndexChanging" ShowHeader="False" >

                                     <Columns>

                                         <asp:CommandField ShowDeleteButton="True" />

                                         <asp:TemplateField>

                                             <ItemTemplate>

                                                 <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl=<%#"~/humanperson_role_set.aspx?"+Container.DataItem%>     

                                                     Text="設定角色"></asp:HyperLink>

                                             </ItemTemplate>

                                         </asp:TemplateField>

                                     </Columns>

                        </asp:GridView></td>

                          </form>

</body>

</html>

背景:  if (!IsPostBack)

        {

            this.GridView1.DataSource = Roles.GetAllRoles();

            this.GridView1.DataBind();

        }

最近發現資料綁定的一些東西,以下是我轉的

.NET使用動态編譯技術,在運作時動态将同一目錄的*.aspx檔案先生成*.cs,然後調用CompilerServices将其編譯成assemblies(可以到你的%SYSTEMROOT%/Microsoft.NET/Framework/V1.x.xxxx/Temporary ASP.NET Files下面看看)。是以了解ASP.NET編譯的過程是優化ASP.NET運作效率的關鍵之一。以常用的資料綁定文法為例,我們可以發現它的轉化規則是:

.aspx: 

->

.cs: System.Convert.ToString(data-binding expression);

其中data-binding expression是原封不動複制過來的,這樣你寫資料綁定表達式的時候就心裡有譜了吧。關于常見于資料綁定表達式中的Container、DataItem、DataBinder.Eval是這樣:DataBinder是System.Web裡面的一個靜态類,它提供了Eval方法用于簡化資料綁定表達式的編寫,但是它使用的方式是通過Reflection等開銷比較大的方法來達到易用性,是以其性能并不是最好的。而Container則根本不是任何一個靜态的對象或方法,它是ASP.NET頁面編譯器在資料綁定事件處理程式内部聲明的局部變量,其類型是可以進行資料綁定的控件的資料容器類型(如在Repeater内部的資料綁定容器叫RepeaterItem),在這些容器類中基本都有DataItem屬性,是以你可以寫Container.DataItem,這個屬性傳回的是你正在被綁定的資料源中的那個資料項。如果你的資料源是DataTable,則這個資料項的類型實際是DataRowView。

現在你可以想想下面哪種寫法效率最高(以Repeater+DataTable資料源為例):

  1. <@% DataBinder.Eval(Container.DataItem, "ColumnName") %>
  2. <@% DataBinder.Eval(Container.DataItem, "ColumnName", null) %>
  3. <@% DataBinder.Eval(Container, "DataItem.ColumnName", null) %>
  4. <@% ((DataRowView)Container.DataItem)["ColumnName"] %>
  5. <@% ((DataRowView)Container.DataItem).Row["ColumnName"] %>

NOTE: 後兩種用法需要引入System.Data名稱空間……答案一天後揭曉,歡迎有空的朋友自己測試得出結論!

如何gridview綁定到數組上面,并設定超連結

揭曉+簡要分析:

乍一看1-3都是使用DataBinder.Eval方法來進行資料綁定計算,而4-5是使用strong type直接擷取資料綁定的值。按照我之前的推理,很多朋友會認為4-5都會比1-3快,而實際上第4種用法也是在網上很常見的一種針對DataBinder.Eval而進行的“優化”。

實際上根據我們的測試,第4種寫法的效率在某些很常見的情形下(即傳入的字段名與資料表内部的字段名大小寫有出入時)甚至比不上最普遍的第1種寫法。不過原理還是對的,就是避免通過reflection或類似機制(如System.ComponentModel中的PropertyDescriptor機制)獲得資料,然而使用DataRowView的indexer的效率在字段數量較多導緻Hashtable産生尋址沖突時不如使用其Row屬性(DataRow類型)的indexer的效率。原因是DataRowView的indexer實作了view的功能,而這個功能對于大多數應用在這個場合都是不需要的,且它的開銷甚至比DataBinder.Eval還要大!(本段内容過于武斷,在被反複質疑之下我又做了若幹試驗尋得正确原因)是以簡單的使用第五種寫法通常是可以獲得較佳的性能的,而最好不要在不必要的時候直接使用DataRowView的indexer。

現在回到1-3的讨論。首先一點,請大家注意看Eval方法的二種overload:

object DataBinder.Eval(object container, string expression)

string DataBinder.Eval(object container, string expression, string format)

注意到ASP.NET在生成的.cs檔案中是使用System.Convert.ToString來将Eval的結果轉換成string的,是以顯式的提供值為null或String.Empty的format參數将使得Eval首先調用第一種方法得到綁定結果的對象,然後直接調用該對象的ToString()方法将其傳回到Convert.ToString方法,對于該方法編譯器已經在編譯期将其連接配接到Convert.ToString(string)的重載上,而該方法則直接傳回傳入的字串。那如果直接使用第一種方法呢?雖然第二種方法是先調用第一種方法的,但是由于它的傳回值是object類型,編譯器将為其選擇Convert.ToString(object)的重載,在這個重載方法中将進行一些額外的判斷以将對象轉換為string類型,而這些額外判斷顯然帶來了額外的開銷——盡管基本上算不得主要沖突。

至于說第3種寫法,由于在expression參數中多引入了一層間接,是以需要多進行一次反射以解析表達式,是以效率非常之低。

那這裡再賣個關子,請推測第5種方法是否還可以進一步優化?(我是指在最常見的ASP.NET開發情形中):P

通過上面的分析,我們可以得到下面的結論:

  1. DataBinder.Eval是最常用也比較易用的資料綁定表達式寫法,但由于其實作機制使用了反射,是以需要關注其所帶來的性能損失。通常,當應用開發進入穩定期後可以針對性的對這些表達式進行優化。
  2. 但是優化不是光從字面上就能感覺到的,第4種所謂優化随處可見,然而在某些情況下它反而帶來其他環節的開銷,帶來比較低的執行效率。
  3. 要注意方法重載是一種編譯期機制,通過顯式告訴編譯器需要使用的方法重載,通常可以在得到同樣結果的前提下獲得更佳的性能。
  4. 性能雖重要,功能價更高——在一般的項目開發中,還是首先關注功能的實作,然後再通過實際測試有針對性的優化比較突出的性能瓶頸。

希望我的這點兒心得對您有所啟發。:)

.NET使用動态編譯技術,在運作時動态将同一目錄的*.aspx檔案先生成*.cs,然後調用CompilerServices将其編譯成assemblies(可以到你的%SYSTEMROOT%/Microsoft.NET/Framework/V1.x.xxxx/Temporary ASP.NET Files下面看看)。是以了解ASP.NET編譯的過程是優化ASP.NET運作效率的關鍵之一。以常用的資料綁定文法為例,我們可以發現它的轉化規則是:

.aspx: 

->

.cs: System.Convert.ToString(data-binding expression);

其中data-binding expression是原封不動複制過來的,這樣你寫資料綁定表達式的時候就心裡有譜了吧。關于常見于資料綁定表達式中的Container、DataItem、DataBinder.Eval是這樣:DataBinder是System.Web裡面的一個靜态類,它提供了Eval方法用于簡化資料綁定表達式的編寫,但是它使用的方式是通過Reflection等開銷比較大的方法來達到易用性,是以其性能并不是最好的。而Container則根本不是任何一個靜态的對象或方法,它是ASP.NET頁面編譯器在資料綁定事件處理程式内部聲明的局部變量,其類型是可以進行資料綁定的控件的資料容器類型(如在Repeater内部的資料綁定容器叫RepeaterItem),在這些容器類中基本都有DataItem屬性,是以你可以寫Container.DataItem,這個屬性傳回的是你正在被綁定的資料源中的那個資料項。如果你的資料源是DataTable,則這個資料項的類型實際是DataRowView。

現在你可以想想下面哪種寫法效率最高(以Repeater+DataTable資料源為例):

  1. <@% DataBinder.Eval(Container.DataItem, "ColumnName") %>
  2. <@% DataBinder.Eval(Container.DataItem, "ColumnName", null) %>
  3. <@% DataBinder.Eval(Container, "DataItem.ColumnName", null) %>
  4. <@% ((DataRowView)Container.DataItem)["ColumnName"] %>
  5. <@% ((DataRowView)Container.DataItem).Row["ColumnName"] %>

NOTE: 後兩種用法需要引入System.Data名稱空間……答案一天後揭曉,歡迎有空的朋友自己測試得出結論!

如何gridview綁定到數組上面,并設定超連結

揭曉+簡要分析:

乍一看1-3都是使用DataBinder.Eval方法來進行資料綁定計算,而4-5是使用strong type直接擷取資料綁定的值。按照我之前的推理,很多朋友會認為4-5都會比1-3快,而實際上第4種用法也是在網上很常見的一種針對DataBinder.Eval而進行的“優化”。

實際上根據我們的測試,第4種寫法的效率在某些很常見的情形下(即傳入的字段名與資料表内部的字段名大小寫有出入時)甚至比不上最普遍的第1種寫法。不過原理還是對的,就是避免通過reflection或類似機制(如System.ComponentModel中的PropertyDescriptor機制)獲得資料,然而使用DataRowView的indexer的效率在字段數量較多導緻Hashtable産生尋址沖突時不如使用其Row屬性(DataRow類型)的indexer的效率。原因是DataRowView的indexer實作了view的功能,而這個功能對于大多數應用在這個場合都是不需要的,且它的開銷甚至比DataBinder.Eval還要大!(本段内容過于武斷,在被反複質疑之下我又做了若幹試驗尋得正确原因)是以簡單的使用第五種寫法通常是可以獲得較佳的性能的,而最好不要在不必要的時候直接使用DataRowView的indexer。

現在回到1-3的讨論。首先一點,請大家注意看Eval方法的二種overload:

object DataBinder.Eval(object container, string expression)

string DataBinder.Eval(object container, string expression, string format)

注意到ASP.NET在生成的.cs檔案中是使用System.Convert.ToString來将Eval的結果轉換成string的,是以顯式的提供值為null或String.Empty的format參數将使得Eval首先調用第一種方法得到綁定結果的對象,然後直接調用該對象的ToString()方法将其傳回到Convert.ToString方法,對于該方法編譯器已經在編譯期将其連接配接到Convert.ToString(string)的重載上,而該方法則直接傳回傳入的字串。那如果直接使用第一種方法呢?雖然第二種方法是先調用第一種方法的,但是由于它的傳回值是object類型,編譯器将為其選擇Convert.ToString(object)的重載,在這個重載方法中将進行一些額外的判斷以将對象轉換為string類型,而這些額外判斷顯然帶來了額外的開銷——盡管基本上算不得主要沖突。

至于說第3種寫法,由于在expression參數中多引入了一層間接,是以需要多進行一次反射以解析表達式,是以效率非常之低。

那這裡再賣個關子,請推測第5種方法是否還可以進一步優化?(我是指在最常見的ASP.NET開發情形中):P

通過上面的分析,我們可以得到下面的結論:

  1. DataBinder.Eval是最常用也比較易用的資料綁定表達式寫法,但由于其實作機制使用了反射,是以需要關注其所帶來的性能損失。通常,當應用開發進入穩定期後可以針對性的對這些表達式進行優化。
  2. 但是優化不是光從字面上就能感覺到的,第4種所謂優化随處可見,然而在某些情況下它反而帶來其他環節的開銷,帶來比較低的執行效率。
  3. 要注意方法重載是一種編譯期機制,通過顯式告訴編譯器需要使用的方法重載,通常可以在得到同樣結果的前提下獲得更佳的性能。
  4. 性能雖重要,功能價更高——在一般的項目開發中,還是首先關注功能的實作,然後再通過實際測試有針對性的優化比較突出的性能瓶頸。

希望我的這點兒心得對您有所啟發。:)