紧凑型框架 SqlDataReader 与 SqlDataAdapter

Compact-Framework SqlDataReader vs SqlDataAdapter

我正在开发一款适用于手持扫描仪设备的旧应用程序 运行 SQL Server CE 和 .Net 3.5。

我的问题与使用 SqlCeDataReaderSqlCeDataAdapter 之间的性能有关。我读过很多文章,指出 DataReaderDataAdapter 快得多,因为它的开销要少得多,并且一次直接记录一条记录,而不是将 "Fill" 批量写入数据 table 或数据集。

现有的应用程序使用 DataAdapter,而我正在尝试进行改型以实现 DataReader,但发现手持设备上的 DataReader 速度较慢,这完全令人困惑我.

总而言之,这是一个简化版本,因为其他帖子也有类似的内容

创建 table...45 个字段,而不仅仅是 3 或 4 个字段样本

// Showing more fields just to show variety of columns of not just
// strings, but of other types too   
CREATE TABLE MyTest 
(
   MyTestID     int IDENTITY(1,1) CONSTRAINT MyTestID PRIMARY KEY,
   Fld1    int,
   Fld2    int, 
   ... (more, just stripped for sample)
   fld6    float,
   Fld7    nchar(2),
   Fld8    float,
   Fld9    nchar(2),
   Fld10   int,
   ... (more, just stripped for sample)
   Fld24   DATETIME, 
   Fld25   nchar(1), 
   Fld26   nchar(15), 
   Fld27   nvarchar(15), 
   ... (more, just stripped for sample)
   Fld44   DATETIME, 
   Fld45   int )

在此之后,我有一个class,其最基本的格式是

public class CTypedClass1
{
   public int Fld1 { get; set; }
   public int Fld2 { get; set; }
   ... etc..
   public double Fld6 { get; set; }
   public double Fld7 { get; set; }
   public string Fld8 { get; set; }
   ... etc to field 45
}

然后我有两个方法循环计数 100 条记录,相应地调用数据适配器与 DataReader 查询的方法

private void ReadMyTestByAdapter()
{
   var cmd = MyConnection.GetSQLDbCommand( "Select * from MyTest where MyTestID = @nMyTestParm" );
   cmd.Parameters.Add( "nMyTestParm", 1 );
   var da = MyConnection.GetSQLDataAdapter();
   da.SelectCommand = cmd;

   for (int i = 1; i < 100; i++)
   {
      DataTable tmpTbl = new DataTable();
      da.SelectCommand.Parameters[0].Value = i;
      QueryByDataAdapter(da, tmpTbl);
   }
}

private void ReadMyTestByTypedClass()
{
   var cmd = MyConnection.GetSQLDbCommand("Select * from MyTest where MyTestID = @nMyTestParm");
   cmd.Parameters.Add("nMyTestParm", 1);

   for (int i = 1; i < 100; i++)
   {
      CTypedClass1 tmpRec = new CTypedClass1();
      cmd.Parameters[0].Value = i;
      QueryByStruct(cmd, tmpRec);
   }
}

现在,通过数据适配器查询并将结果填充到 DataTable

private void QueryByDataAdapter(SqlCeDataAdapter da, DataTable putInHere )
{
   if (da.SelectCommand.Connection.State != ConnectionState.Open)
      da.SelectCommand.Connection.Open();

   da.Fill(putInHere);

   if (da.SelectCommand.Connection.State == ConnectionState.Open)
      da.SelectCommand.Connection.Close();
}

并尝试防止反射开销​​,我正在尝试将数据 reader 直接用于类型化 class.

的属性中
private void QueryByStruct(SqlCeCommand cmd, CTypedClass1 curRec)
{
   if (cmd.Connection.State != ConnectionState.Open)
      cmd.Connection.Open();

   using (var reader = cmd.ExecuteReader())
   {
      while (reader.Read())
      {
         curRec.Fld1 = (int)reader["Fld1"];
         curRec.Fld2 = (int)reader["Fld2"];
         // etc with rest of fields to 45
         // all explicitly (typecast) referenced
      }
   }

   if (cmd.Connection.State == ConnectionState.Open)
      cmd.Connection.Close();
}

该过程实际上执行了 table 的所有 45 个字段,并且两种方法之间的性能几乎相同,在 9 秒内读取 100 条记录,每次都单独查询一个 ID。 Typed 格式使用的表观内存小于 DataTable/DataAdapter,这也令人困惑,因为 Typed 仅存储值的一个实例,但 DataTable 结果在行级别具有整个 ItemArray,并且具有当前值、默认值和原始值的 DataRowVersion。

这没有任何意义,希望有人能为我阐明这一点。

注意:如果我在台式机上做完全相同的事情(针对不同的数据库,但连接、查询等分别相同),typed-class 方法大约是 6 次比数据适配器方法更快。

根据我的经验,使用 reader[string] 很慢。当我在 HandHeld 扫描仪上为 CE 开发时,我使用了类似下面的东西:(不要使用 DataAdapter,它比较慢)

private void QueryByStruct(SqlCeCommand cmd, CTypedClass1 curRec)
{
   if (cmd.Connection.State != ConnectionState.Open)
      cmd.Connection.Open();

   List<object> fields;

   using (var reader = cmd.ExecuteReader())
   {
      if (reader.Read())
      {
          var values = new Object[reader.FieldCount];
          reader.GetValues(values);
          fields = values.ToList();
      }
   }

   if (cmd.Connection.State == ConnectionState.Open)
      cmd.Connection.Close();

   curRec.Fld1 = (int)fields.ElementAt(1);
   curRec.Fld2 = (int)fields.ElementAt(2);
   // etc with rest of fields to 45
   // all explicitly (typecast) referenced

}

我将 while 更改为 if,因为看起来您只是无缘无故地覆盖了值。 GetValues() 根据我的经验,速度确实非常快。缺点是您只能按列顺序获取值,没有列类型或列名。

也不错-微软SQL Server Compact Edition Ultimate Performance Tuning:

Video Channel

Microsoft SQL Server Compact Edition Ultimate Performance Tuning Powerpoint Presentation (direct link)