[转载]数据绑定以及Container.DataItem的具体分析

 常见的数据绑定操作:
       简单属性:     <%#UserName%>
       集合:          <asp:ListBox id="ListBox1" datasource='<%# myArray%>' runat="server">
       表达式:       <%#(class1.property1.ToString() + "," + class1.property2.ToString())%>
       方法返回值 :<%# GetSafestring(str) %>
       Hashtable: <%# ((DictionaryEntry)Container.DataItem).Key%>
       ArrayList:  <%#Container.DataItem %>
 
        若数组里里放的是对象则可能要进行必要的转换后再绑定如:
        <%#((对象类型)Container.DataItem).属性%>
 
        绑定到DataView,DataTable,DataSet:
        <%#((DataRowView)Container.DataItem)["字段名"]%>或
        <%#((DataRowView)Container.DataItem).Rows[0]["字段名"]%>
        要格式化则:
        <%#string.Format("格式",((DataRowView)Container.DataItem)["字段名"])%>
        <%#DataBinder.Eval(Container.DataItem,"字段名","格式")%>
 
        绑定到DataReader:
        <%#((IDataReader)Container.DataItem).字段名%>
 
        一般为了方便用最多的就是DataBinder类的Eval方法.不过这样对于同时要绑定大量的数据效率要低一些
 
在绑定数据时经常会用到这个句程序:
<%# DataBinder.Eval(Container.DataItem,"xxxx")%>
或者<%# DataBinder.Eval(Container,"DataItem.xxxx")%>
今天又了解到一种,而且微软说这种方法的效率要比以上两种高
<%# ((DataRowView)Container.DataItem)["xxxx"]%>
 
感觉很有用,这样可以在前台页面做好多事情了。
 
还要记住要这样用必须要在前台页面导入名称空间System.Data,否则会生成错误信息。
<%@ Import namespace="System.Data" %>
 
这种用法其实和<%# ((DictionaryEntry)Container.DataItem).Key%>是一个道理。
 
绑定到DataSet、DataTable时:
<%#((System.Data.DataRowView)Container.DataItem)["字段名"]%>
<%#((System.Data.DataRowView)Container.DataItem)[索引]%>
 
绑定到DataReader时:
<%#((System.Data.Common.DbDataRecord)Container.DataItem)[索引]%>
<%#((System.Data.Common.DbDataRecord)Container.DataItem)["字段名"]%>
 
关键是Container这个对象。它的名称空间是System.ComponentModel。
 
初学.NET,现在再看DataGrid控件,在ItemTemplate显示数据时,
DataBinder.Eval(Container.DataItem,"Name")和Container.DataItem("Name")有什么区别?
 
DataBinder是System.Web里面的一个静态类,它提供了Eval方法用于简化数据绑定表达式的编写,但是它使用的方式是通过Reflection等开销比较大的方法来达到易用性,因此其性能并不是最好的。而Container则根本不是任何一个静态的对象或方法,它是ASP.NET页面编译器在数据绑定事件处理程序内部声明的局部变量,其类型是可以进行数据绑定的控件的数据容器类型(如在Repeater内部的数据绑定容器叫RepeaterItem),在这些容器类中基本都有DataItem属性,因此你可以写Container.DataItem,这个属性返回的是你正在被绑定的数据源中的那个数据项。如果你的数据源是DataTable,则这个数据项的类型实际是DataRowView。
 
ASP.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);


现在你可以想想下面哪种写法效率最高(以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"] %>


乍一看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:
objectDataBinder.Eval(objectcontainer,stringexpression)
stringDataBinder.Eval(objectcontainer,stringexpression,stringformat)
注意到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参数中多引入了一层间接,因此需要多进行一次反射以解析表达式,因此效率非常之低。


通过上面的分析,我们可以得到下面的结论:
1. DataBinder.Eval是最常用也比较易用的数据绑定表达式写法,但由于其实现机制使用了反射,所以需要关注其所带来的性能损失。通常,当应用开发进入稳定期后可以针对性的对这些表达式进行优化。
2. 优化不是光从字面上就能感觉到的,第4种所谓优化随处可见,然而在某些情况下它反而带来其他环节的开销,则带来比较低的执行效率。
3. 注意方法重载是一种编译期机制,通过显式告诉编译器需要使用的方法重载,通常可以在得到同样结果的前提下获得更佳的性能。
4. 性能虽重要,但是在一般的项目开发中,还是首先关注功能的实现,然后再通过实际测试有针对性的优化比较突出的性能瓶颈。

 

转载于:https://www.cnblogs.com/chqyang/archive/2009/04/30/1447294.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值