ASP.NET中数据邦定效率问题的一点看法
2011-09-15 17:51
375 查看
在做Asp.NET开发的时候经常用到DataList、Repeater等,用这些控件的时候经常用到数据邦定,很多程序员都是按照MS提供的方法<%#DataBinder.Eval(Container.DataItem,"xxx") %>进行邦定,经常听人说这样邦定效率低,那么到底哪里引起的效率低呢?不妨大家打开MS的代码来看看他是这么实现这个数据邦定的,这样一切都清楚了。DataBinder是System.Web.UI中的一个静态类。首先看一下它的Eval方法:
这个方法调用了另外一个重载的Eval方法我们接着看这个方法:
在这个方法中有一个GetIndexedPropertyValue方法是处理索引用的,一般邦定用到的是上边的GetPropertyValue方法。继续看GetPropertyValue方法:
晕~~ 这个方法中利用TypeDescriptor的GetProperties方法将邦定对象反射然后用GetValue获取我们想要的值! 看到这里我想大家都已经看清楚了,原来当我们调用<%#DataBinder.Eval(Container.DataItem,"xxx") %>时是将Container.DataItem反射然后用GetValue取值的,也就是说如果你页面中有多个DataBinder的话每个都要反射、取值!晕倒~ 反射是非常消耗资源而且效率低下的这个不用我说了。对于反射只有在动态加载程序集或者在未知数据类型的情况下不得已才用得,显然我们对我们要邦定的数据既不需要动态加载也不是未知数据类型,那么完全没有必要用这个既浪费资源又非常慢的技术。看来MS提供的这个DataBinder.Eval玩意儿真不是什么好东西,呵呵。
不过咱们稍微改进一下效率可以提高数十倍甚至数百倍。既然大家知道瓶颈出在反射上那咱们就不用反射,怎么办呢?答案是不用DataBinder.Eval邦定,具体如下:
第一种方法:这种方法好多地方介绍过。用在邦定页面上把Container.DataItem转换为邦定类型,如:我们在用DataTable做数据源的时候其实Container.DataItem就是DataRowView那么把Container.DataItem转换为DataRowView不就可以用索引直接取值了吗?:<%#((DataRowView)Container.DataItem)["xxx"]%> 哈哈,这样效率有大幅度提升,尤其在数据量大的时候。
第二种方法:上一种方法虽好但是每次取值的时候都要转换一下,还不够完美。能不能一下转过来然后再所有邦定中直接取呢?答案是肯定的!我们可以在DataList、Repeater的ItemCreated事件中做文章,我们在定义一个protected 变量,变量类型为邦定数据类型。如protected DataRowView Info =null; 然后再ItemCreated中进行转换付值。最后在前台邦定时写成?<%#Info ["xxx"]%>代码:
如果用户用IList<T>做数据源就更简单了:
前台邦定变为<%#Info.Title%>
总结:MS确实提供了很多方便快捷的功能,但是方便和快捷的背后是性能的损失,这些方便快捷的方法只是提供给一些初级阶段的程序员来更快的完成一些工作,他们并不注重效率。但是如果要求高效率那么就要自己动手,这就要求我们要对.NET要有深刻的认识,所以要想成为高手必须深入理解.NET机理,做到随心所欲。
转自刘晓飞Blog:http://www.cnblogs.com/lxsfg/articles/849128.html
public static object Eval (object container, string expression) { if (expression == null) { throw new ArgumentNullException("expression"); } expression = expression.Trim(); if (expression.Length == 0) { throw new ArgumentNullException("expression"); } if (container == null) { return null; } return DataBinder.Eval(container, expression.Split(DataBinder.expressionPartSeparator)); }
这个方法调用了另外一个重载的Eval方法我们接着看这个方法:
private static object Eval (object container, string[] expressionParts) { object obj1 = container; for (int num1 = 0;(num1 < expressionParts.Length) && (obj1 != null); num1++) { string text1 = expressionParts[num1]; if (text1.IndexOfAny(DataBinder.indexExprStartChars) < 0) { obj1 = DataBinder.GetPropertyValue(obj1, text1); } else { obj1 = DataBinder.GetIndexedPropertyValue(obj1, text1); } } return obj1; }
在这个方法中有一个GetIndexedPropertyValue方法是处理索引用的,一般邦定用到的是上边的GetPropertyValue方法。继续看GetPropertyValue方法:
public static object GetPropertyValue (object container, string propName) { if (container == null) { throw new ArgumentNullException("container"); } if (string.IsNullOrEmpty(propName)) { throw new ArgumentNullException("propName"); } object obj1 = null; PropertyDescriptor descriptor1 = TypeDescriptor.GetProperties(container).Find(propName, true); if (descriptor1 == null) { throw new HttpException(SR.GetString("DataBinder_Prop_Not_Found", new object[]{container.GetType().FullName, propName})); } return descriptor1.GetValue(container); }
晕~~ 这个方法中利用TypeDescriptor的GetProperties方法将邦定对象反射然后用GetValue获取我们想要的值! 看到这里我想大家都已经看清楚了,原来当我们调用<%#DataBinder.Eval(Container.DataItem,"xxx") %>时是将Container.DataItem反射然后用GetValue取值的,也就是说如果你页面中有多个DataBinder的话每个都要反射、取值!晕倒~ 反射是非常消耗资源而且效率低下的这个不用我说了。对于反射只有在动态加载程序集或者在未知数据类型的情况下不得已才用得,显然我们对我们要邦定的数据既不需要动态加载也不是未知数据类型,那么完全没有必要用这个既浪费资源又非常慢的技术。看来MS提供的这个DataBinder.Eval玩意儿真不是什么好东西,呵呵。
不过咱们稍微改进一下效率可以提高数十倍甚至数百倍。既然大家知道瓶颈出在反射上那咱们就不用反射,怎么办呢?答案是不用DataBinder.Eval邦定,具体如下:
第一种方法:这种方法好多地方介绍过。用在邦定页面上把Container.DataItem转换为邦定类型,如:我们在用DataTable做数据源的时候其实Container.DataItem就是DataRowView那么把Container.DataItem转换为DataRowView不就可以用索引直接取值了吗?:<%#((DataRowView)Container.DataItem)["xxx"]%> 哈哈,这样效率有大幅度提升,尤其在数据量大的时候。
第二种方法:上一种方法虽好但是每次取值的时候都要转换一下,还不够完美。能不能一下转过来然后再所有邦定中直接取呢?答案是肯定的!我们可以在DataList、Repeater的ItemCreated事件中做文章,我们在定义一个protected 变量,变量类型为邦定数据类型。如protected DataRowView Info =null; 然后再ItemCreated中进行转换付值。最后在前台邦定时写成?<%#Info ["xxx"]%>代码:
protected DataRowView Info = null; protected void RepInfoList_ItemCreated(object sender, RepeaterItemEventArgs e) { Info = e.Item.DataItem as DataRowView; }
如果用户用IList<T>做数据源就更简单了:
protected BbsInfo Info =null; protected void RepInfoList_ItemCreated(object sender, RepeaterItemEventArgs e) { Info = e.Item.DataItem as BbsInfo }
前台邦定变为<%#Info.Title%>
总结:MS确实提供了很多方便快捷的功能,但是方便和快捷的背后是性能的损失,这些方便快捷的方法只是提供给一些初级阶段的程序员来更快的完成一些工作,他们并不注重效率。但是如果要求高效率那么就要自己动手,这就要求我们要对.NET要有深刻的认识,所以要想成为高手必须深入理解.NET机理,做到随心所欲。
转自刘晓飞Blog:http://www.cnblogs.com/lxsfg/articles/849128.html
相关文章推荐
- ASP.NET中数据邦定效率问题的一点看法
- 解决Asp.net Mvc返回JsonResult中DateTime类型数据格式的问题
- [ASP.NET]解决“试图将 Null 值赋予一个非 Variant 数据类型的变量”的问题
- 解决asp.net MVC 的数据访问并发问题。(已有打开的与此 Command 相关联的 Dat)
- ASP.NET: TextBox控件如果设置为ReadOnly则PostBack之后可能丢失数据的问题
- 总结Asp.net中Page加载PostData的具体过程 进而解决"获取动态创建的控件的PostData数据"问题
- 关于asp.net的一点小问题有谁帮忙解答一下?
- ASP.NET页面借助IFrame提交表单数据所遇到的问题
- asp.net repeater数据邦定
- The NOTE of learning ASP.NET [10] 关于.NET整型与浮点型变量使用上的效率和存储问题
- 在Asp.net 2.0 中禁用页面缓存解决页面刷新(重新加载数据)的问题!
- Asp.Net中页面内数据的保存和性能问题探讨
- ASP.NET数据控件绑定需要注意的问题
- asp.net 学习笔记[02] 便捷数据邦定
- ASP.NET中使用数据处理插入数据注意的问题
- asp.net 数据绑定 使用eval 时候报 字符文本中的字符太多 问题的解决方法
- asp.net关于分页上的数据删除问题
- asp.net 脏字典过滤问题 用正则表达式来过滤脏数据
- asp.net读excle的数据类型不统一取出空值问题
- asp.net 确认对话框与数据验证控件的冲突问题