DataReder填充对象集比DataAdapter.Fill效率要高?
在做一个数据组件时查询时要把数据集转成对象集;在测试过程中看到的结果自己的感觉有点意外.DataReder填充对象集比DataAdapter.Fill填充到DataSet效率要高!DataAdapter.Fill内部工作原理没有去了解,但对象集是强类型的在数据转换存在拆箱,而DataSet不是强类型的按道理是填充DataSet在效率上占优越,但测试结果确相反!
测试代码如下(获取所有订单记录830条):
System.IO.StreamWriter write = new System.IO.StreamWriter(@"c:\testReader.txt");
Console.SetOut(write);
using(System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection("data source=.;initial catalog=northwind;user id=sa;pwd=;"))
{
XSF.XUtils.XCounter counter = new XSF.XUtils.XCounter();
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
cmd.CommandText ="select * from Orders";
cmd.Connection = conn;
conn.Open();
for(int i =0;i<20;i++)
{
counter.Start();
using(System.Data.IDataReader reader = cmd.ExecuteReader())
{
System.Collections.ArrayList list = new System.Collections.ArrayList();
counter.Start();
while(reader.Read())
{
Example.Entitys.OrdersOjb order = new Example.Entitys.OrdersOjb();
order.LoadInfo(reader);
list.Add(reader);
}
counter.Stop();
Console.Write(" Orders:"+counter.Duration.ToString("0.000000000000000000000000000"+"\r\n"));
}
counter.Stop();
System.Data.SqlClient.SqlDataAdapter da = new System.Data.SqlClient.SqlDataAdapter(cmd);
System.Data.DataSet myDS = new System.Data.DataSet();
counter.Start();
da.Fill(myDS);
counter.Stop();
Console.Write("DataSet:"+counter.Duration.ToString("0.000000000000000000000000000"+"\r\n\r\n"));
}
}
write.Close();
表对应的映射对象
[Serializable]
public class OrdersOjb
{
...
...
public void LoadInfo(System.Data.IDataReader pDataReader)
{
if( pDataReader[0] != DBNull.Value)
{
this.OrderID= (Int32)pDataReader[0];
}
if( pDataReader[1] != DBNull.Value)
{
this.CustomerID= (String)pDataReader[1];
}
if( pDataReader[2] != DBNull.Value)
{
this.EmployeeID= (Int32)pDataReader[2];
}
if( pDataReader[3] != DBNull.Value)
{
this.OrderDate= (DateTime)pDataReader[3];
}
if(pDataReader[4] != DBNull.Value)
{
this.RequiredDate= (DateTime)pDataReader[4];
}
if(pDataReader[5] != DBNull.Value)
{
this.ShippedDate= (DateTime)pDataReader[5];
}
if( pDataReader[6] != DBNull.Value)
{
this.ShipVia= (Int32)pDataReader[6];
}
if( pDataReader[7] != DBNull.Value)
{
this.Freight= (Decimal)pDataReader[7];
}
if( pDataReader[8] != DBNull.Value)
{
this.ShipName= (String)pDataReader[8];
}
if( pDataReader[9] != DBNull.Value)
{
this.ShipAddress= (String)pDataReader[9];
}
if( pDataReader[10] != DBNull.Value)
{
this.ShipCity= (String)pDataReader[10];
}
if( pDataReader[11] != DBNull.Value)
{
this.ShipRegion= (String)pDataReader[11];
}
if( pDataReader[12] != DBNull.Value)
{
this.ShipPostalCode= (String)pDataReader[12];
}
if( pDataReader[13] != DBNull.Value)
{
this.ShipCountry= (String)pDataReader[13];
}
}
}
在映射对象中记获取DataReader时并没有用到字段名而是用索引,因为在测试时用索引获取比用键值获取大概快(2-3微秒),就是这一点效率的差别把整个情况扭转了(效率由原来慢大概50%变成快大概25%).
测试的结果:
Orders:0.055864642014557700000000000
DataSet:0.110196687009103000000000000
Orders:0.023227253743143300000000000
DataSet:0.020698999453841200000000000
Orders:0.016390910017893300000000000
DataSet:0.023404929956181600000000000
Orders:0.017637995890539200000000000
DataSet:0.025213819074770700000000000
Orders:0.017227887901954000000000000
DataSet:0.024791977751362300000000000
Orders:0.017724040345909900000000000
DataSet:0.022490009205080500000000000
Orders:0.023765031589210400000000000
DataSet:0.021654986876823700000000000
Orders:0.015963760757303000000000000
DataSet:0.021302707467010500000000000
Orders:0.015803405181384800000000000
DataSet:0.020940929643292700000000000
Orders:0.015981081394423000000000000
DataSet:0.020426059736642500000000000
Orders:0.015780217876853100000000000
DataSet:0.024939482531997800000000000
Orders:0.015689982944759700000000000
DataSet:0.020697043898037300000000000
Orders:0.015734681363134100000000000
DataSet:0.021563913849385900000000000
Orders:0.026096892202780000000000000
DataSet:0.020594516900891000000000000
Orders:0.015682998816888700000000000
DataSet:0.020990656633734200000000000
Orders:0.015992255999016600000000000
DataSet:0.021358021759748800000000000
Orders:0.016322465564757500000000000
DataSet:0.020486961331677600000000000
Orders:0.015694173421482300000000000
DataSet:0.028225933742975700000000000
Orders:0.015794744862824700000000000
DataSet:0.022132701223200200000000000
Orders:0.015866821062453500000000000
DataSet:0.020778059781340900000000000
不过填充对象集就缺少了很多DataSet的功能.针对每个映射对象来编写获取信息方法也是一个很大的工作量,不过可以利用CodeDom在运行时动太生成操作对象来代替相关的工作量(CodeDom应用描述:http://henryfan.cnblogs.com/archive/2005/11/28/286036.html)。