Compact-Framework SqlDataReader vs SqlDataAdapter
本文关键字:SqlDataAdapter vs SqlDataReader Compact-Framework | 更新日期: 2023-09-27 18:25:51
我正在开发一款较旧的应用程序,该应用程序与运行SQL Server CE和.Net 3.5的手持扫描仪设备配合使用。
我的问题与使用SqlCeDataReader
和SqlCeDataAdapter
之间的性能有关。我读过很多关于DataReader
比DataAdapter
快得多的文章,因为它的开销要小得多,而且与批量"填充"到数据表或数据集中相比,它一次只直接一条记录。
现有的应用程序使用DataAdapter
,而我正试图对DataReader
进行改造,但在手持设备上发现DataReader
很慢,这让我完全困惑
总之,这是一个简化的版本,因为其他帖子也有类似的
正在创建表。。。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 )
在这之后,我有一个类,它最基本的格式是
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();
}
为了防止反射开销,我尝试将数据读取器直接用于类型化类的属性。
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();
}
该过程实际上处理了表中的所有45个字段,两种方法在9秒内读取100条记录时的性能几乎相同,每次都单独查询一个ID。Typed格式使用的表观内存小于DataTable/DataAdapter,这也令人困惑,因为Typed只存储一个值实例,但DataTable结果在行级别上具有整个ItemArray,并且具有当前值、默认值和原始值的DataRowVersion。
这没有任何意义,希望有人能为我提供一点线索
注意:如果我在台式机上做同样的事情(针对不同的数据库,但连接、查询等都相同),那么类型化类方法的速度大约是数据适配器方法的6倍。
根据我的经验,使用reader[string]
很慢。当我为手持扫描仪上的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()真的非常快。不利的一面是,只按列顺序获取值,没有列类型也没有列名。
也是一个不错的选择-Microsoft SQL Server Compact Edition终极性能调整:
视频通道
Microsoft SQL Server Compact Edition终极性能调整Powerpoint演示文稿(直接链接)