尽可能用预先排序的数据
ADONET对象模式使我们可以很容易地实现排序你可以创建一个DataView对象并设置其Sort属性ADONET runtime查看新的排序表达式并为视图重编索引该步骤是在内存中实现的但速度并不快排序的花费很高更重要的是它并不是个线性操作(linear operation)对一组数据进行排序需要n*log(n)的计算成本就是说随着需要排序的条目数量的增加直线增加的成本是很大的因此你应该限制应用程序中的排序尽可能地运用预先排序的数据在Web应用程序中动态排序对性能的影响是相当大的既然如此你就应该设计应用程序限制对动态排序的需求并依赖在数据库服务器中写死的算法除非你在用应用程序的一个可以使复杂性低于n*log(n)极限的特殊的功能否则避免运用手工排序算法因为这种算法可能比系统中的算法更糟
ADOX可以帮你得到并改变Schema信息
ADONET并没有为得到并管理schema信息提供一个完全的对象模式你应该用ActiveX Data Objects Extensions for Data Definition Language and Security (ADOX)或用每个数据库提供的本地功能来得到并改变Schema信息ADOX是ADO对象的一个扩展它包括用来创建和修改Schema的对象你可以编写适用于各种数据源的代码(不管本地语法有什么不同)因为ADOX是管理schema的一个基于对象的方法
你可以用一个data reader对象来读(不是设置)简单的schema信息所有的data reader类(OleDbDataReaderSqlDataReaderOracleDataReader)都提供了一个GetSchemaTable方法该方法可以读取查询到的列的元数据信息GetSchemaTable返回一个DataTable对象(格式是每列一行)和固定的一组包含信息的列返回的元数据可以分成三类列元数据数据库特征和列属性返回的列可以是AllowDBNullIsAutoIncrementColumnNameIsExpressionIsReadonly和NumericPrecision等在MSDN资料中有完整的列表(见附加资源)
在调用ExecuteReader时如果你执行KeyInfo命令那么GetSchemaTable方法就可以返回更精确的数据你可以将KeyInfo行为同缺省的行为结合起来执行一个单独的命令并得到schema和数据
reader = cmd
ExecuteReader( _
CommandBehaviorKeyInfo Or _
CommandBehaviorCloseConnection)
只有执行KeyInfoIsKeyBaseTableNameIsAliasedIsExpression和IsHidden字段的值才能被正确返回如果执行KeyInfo关键的列(如果有)通常是添加在结果集的底部的但不给它们返回数据
用一个派生的类和自定义的串行化来节省空间
只有两个ADONET对象是被标记为可串行化的——DataTable和DataSetNET Framework中的串行化是通过formatter对象来完成的它们可以将一个对象实例保存到一个二进制或一个SOAP流(stream)中NET formatter用Reflection来提取任何必要的信息然而如果这个类实现了ISerializable接口那么NET formatter就会给接口的方法让步让它们负责拷贝需要串行化到一个内存缓沖器中的所有的信息DataTable和DataSet类都通过ISerializable接口支持串行化
如果你将一个DataTable或一个DataSet串行到一个二进制(binary stream)中你应该可以得到非常紧凑的输出结果虽然你得到的结果文件是最小的但遗憾的是它实际上并不小荒谬的是你保存到一个二进制的DataSet比你用WriteXml方法保存到XML的同样的DataSet要大很多
要解释这种情况我们需要来看看ADONET对象是用什么方式被串行起来的在串行一个DataSet对象时它将基于XML的DiffGram表示法保存在formatter的缓沖器中在串行一个DataTable时它首先创建了一个临时的DataSet对象将它定义为它的parent然后作为一个DiffGram串行起来
一个DiffGram是一个XML流它提供了一个DataSet中表和行的有状态的表示法一个DiffGram文件是很详细的有些冗长DiffGram包含当前的数据以及被修改的行和未解决的错误的初始值当我们保存一个DataSet或一个DataTable时所有这些信息就会被传递给serializer被串行化的对象总是包含XML数据因此即使当输出流是二进制的时最后的输出结果仍然会很大
你可以创建一个继承DataTable或DataSet的新的可串行化的类来解决这个问题并且更有效地保存ADONET对象你必须用<Serizlizable()>属性来标记新类即使父类是可以串行化的实际上串行性(serizlizability)并不是一个可以自动继承的类属性你从DataTable或DataSet构建的新类也可以实现ISerializable接口当然你可以为新类选择一个不同的串行化方案一个简单而有效的方法就是将DataTable类的所有成员映射到数组和值成员中
运用一个派生的类和一个自定义的串行化方案可以为一个DataSet对象节省多达%的磁盘空间节省的空间的比率取决于DataSet中的数据类型你的数据越基于文本节省的空间越多然而运用二进制的BLOB字段只可以节省大约%的空间(下载一个完整的例子)
选择一个适合你的数据的分页机制
DataGrid服务器控件使我们可以更容易地在Web应用程序中以长度可变的页面来显示数据了该控件有绑定和格式化功能它可以接受一个ADONET数据对象并为浏览器生成HTML代码出于性能的原因在页面的视图状态DataGrid并没有缓存数据源的内容因此当返回页面时你就必须填充grid要实现这一点可以用两种方法在Web服务器上将数据源作为整体或一部分缓存起来然后读回或者对每个请求从物理数据库加载所需的记录如果你选择第一种方法那么数据就从存储中只被读取一次保存在一个缓存中并为以后的postback事件读回我们通常用内存中的全局对象(如Session或Cache)来保存这个数据我们用DataSet来搜集所有需要的数据并将它保存在内存中将一个DataSet对象保存在Session中同ADO中的线程含义并不一样但是通过减少Web服务器可用的内存仍可以影响可扩展性
如果要显示的数据是特定于session的那么在每次返回页面时加载记录页面就比用一个DataSet和ASPNET全局对象来缓存数据要好编写得很好的SQL代码可以将结果集分成许多页再加上DataGrid控件内置的自定义分页机制我们就可以得到最佳的解决方案来保持ASPNET应用程序的可扩展性和良好的性能了
[] [] [] []