在做一個資料群組件時查詢時要把資料集轉成對象集;在測試過程中看到的結果自己的感覺有點意外.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)。