.net 填充数据表时,datareader是否比dataset快?

.net 填充数据表时,datareader是否比dataset快?,.net,performance,datatable,datareader,dataadapter,.net,Performance,Datatable,Datareader,Dataadapter,这样会更快 1) 循环datareader并基于填充的datatable创建自定义行和列 2) 或者创建dataAdapter对象并只(.Fill)填充datatable 在动态创建datatable时,datareader的性能是否仍然有效 DataAdapter在引擎盖下使用DataReader,因此您的体验可能与此相同 DataAdapter的好处是减少了大量需要维护的代码 这场辩论有点宗教色彩,所以一定要环顾四周,决定什么最适合你的情况: 我不能说填充数据表本身,但使用数据读取

这样会更快

1) 循环datareader并基于填充的datatable创建自定义行和列

2) 或者创建dataAdapter对象并只(.Fill)填充datatable


在动态创建datatable时,datareader的性能是否仍然有效

DataAdapter在引擎盖下使用DataReader,因此您的体验可能与此相同

DataAdapter的好处是减少了大量需要维护的代码

这场辩论有点宗教色彩,所以一定要环顾四周,决定什么最适合你的情况:


我不能说填充数据表本身,但使用数据读取器是最有效的读取方法

你的选择#1会更慢。但是,与手动添加自定义行相比,有更好的方法将datareader转换为datatable:

DataTable dt = new DataTable();

using (SqlConnection conn = GetOpenSqlConnection())
using (SqlCommand cmd = new SqlCommand("SQL Query here", conn)
using (IDataReader rdr = cmd.ExecuteReader())
{
    dt.Load(rdr);
}

我无法评论这与使用
.Fill()

之间的区别。例如,当您需要显示加载数据的进度时,有DataReader是很好的选择。在DataSet中,您不能在加载数据的过程中执行某些操作

另一方面,数据集是一体的对象。所以数据集的速度要慢得多。DataReader可以在代码中数据操作非常缓慢的地方为您提供额外的提升。在这些地方,将其从DataSet更改为DataReader。DataReader还占用更少的内存空间

当然,编写好的数据阅读器需要更多的时间,但这是值得的。例如,当您播放从数据库中获取的图像或音乐时


数据阅读器速度更快。如果您使用的是2.0+版本,那么您甚至不必使用datatable。您可以使用对象的通用列表。

假设您确实希望从数据库返回所有数据,那么在数据库和网络上花费的时间几乎肯定会使在内存中填充数据结构的过程中花费的时间相形见绌


是的,在某些情况下,通过使用DataReader,您可能会得到一点节省—特别是如果您想要流式传输数据,它可能会很有用—但是如果您确实需要所有这些,我会坚持使用最简单的代码。如果您认为数据集填充导致了严重的性能问题,请对其进行分析,然后尝试改进。

对于许多类似的问题,答案是:视情况而定

如果您事先不知道数据的结构,并且正在动态创建TableAdapter,那么动态DataTable将更加高效。创建TableAdapter涉及大量代码生成

但是,如果您事先知道数据的结构,那么问题就变成了,我需要多少功能

如果您需要一个完整的CRUD实现,那么使用TableAdapter而不是自己编写所有CRUD代码可以提高一些效率。此外,TableAdapter实现还可以(不是很好)。如果您需要更高效的服务,那么最好使用nHibernate或其他ORM


如果您不需要完整的CRUD实现(即,这是一个只读解决方案),并且预先了解您的数据结构,那么您必须根据动态生成的数据表测试TableAdapter只读实现的效率。如果我是一个赌徒,我会把钱投在TableAdapter实现上,因为你可以绑定一次数据并多次读取。

使用
DataReader
read
,这是一种只向前、一次一行的方法,它按顺序读取数据,这样你在连接时只要读取记录就可以得到记录,将是最好的记忆和性能

也就是说,在这两种方法之间,我发现
IDataAdapter.Fill
DataTable.Load
快得多。当然,这取决于实现。。以下是我发布的两个基准:

公共数据表Read1(字符串查询),其中T:IDbConnection,new() { 使用(var conn=new T()) { 使用(var cmd=conn.CreateCommand()) { cmd.CommandText=查询; cmd.Connection.ConnectionString=\u ConnectionString; cmd.Connection.Open(); var table=新数据表(); Load(cmd.ExecuteReader()); 返回表; } } } 公共数据表Read2(字符串查询),其中S:IDbConnection,new() 其中T:IDbDataAdapter,IDisposable,new() { 使用(var conn=new S()) { 使用(var da=new T()) { 使用(da.SelectCommand=conn.CreateCommand()) { da.SelectCommand.CommandText=查询; da.SelectCommand.Connection.ConnectionString=\u ConnectionString; DataSet ds=new DataSet();//连接由dataadapter打开 da.填充(ds); 返回ds.表[0]; } } } } 第二种方法总是优于第一种方法

Stopwatch sw = Stopwatch.StartNew();
DataTable dt = null;
for (int i = 0; i < 100; i++)
{
    dt = Read1<MySqlConnection>(query); // ~9800ms
    dt = Read2<MySqlConnection, MySqlDataAdapter>(query); // ~2300ms

    dt = Read1<SQLiteConnection>(query); // ~4000ms
    dt = Read2<SQLiteConnection, SQLiteDataAdapter>(query); // ~2000ms

    dt = Read1<SqlCeConnection>(query); // ~5700ms
    dt = Read2<SqlCeConnection, SqlCeDataAdapter>(query); // ~5700ms

    dt = Read1<SqlConnection>(query); // ~850ms
    dt = Read2<SqlConnection, SqlDataAdapter>(query); // ~600ms

    dt = Read1<VistaDBConnection>(query); // ~3900ms
    dt = Read2<VistaDBConnection, VistaDBDataAdapter>(query); // ~3700ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Stopwatch sw=Stopwatch.StartNew();
数据表dt=null;
对于(int i=0;i<100;i++)
{
dt=Read1(查询);//~9800ms
dt=Read2(查询);//~2300ms
dt=Read1(查询);//~4000ms
dt=Read2(查询);//~2000ms
dt=Read1(查询);//~5700ms
dt=Read2(查询);//~5700ms
dt=Read1(查询);//~850ms
dt=Read2(查询);//~600ms
dt=Read1(查询);//~3900ms
dt=Read2(查询);//~3700ms
}
sw.Stop();
Show(sw.eassed.totalmillizes.ToString());
Read1
看起来更好,但数据适配器的性能更好(不要混淆一个数据库的性能优于另一个,查询都是不同的)。不过,两者之间的差异取决于查询。原因可能是
Load
需要在添加行时逐行检查各种约束(这是
DataTable
上的一种方法),而
Stopwatch sw = Stopwatch.StartNew();
DataTable dt = null;
for (int i = 0; i < 100; i++)
{
    dt = Read1<MySqlConnection>(query); // ~9800ms
    dt = Read2<MySqlConnection, MySqlDataAdapter>(query); // ~2300ms

    dt = Read1<SQLiteConnection>(query); // ~4000ms
    dt = Read2<SQLiteConnection, SQLiteDataAdapter>(query); // ~2000ms

    dt = Read1<SqlCeConnection>(query); // ~5700ms
    dt = Read2<SqlCeConnection, SqlCeDataAdapter>(query); // ~5700ms

    dt = Read1<SqlConnection>(query); // ~850ms
    dt = Read2<SqlConnection, SqlDataAdapter>(query); // ~600ms

    dt = Read1<VistaDBConnection>(query); // ~3900ms
    dt = Read2<VistaDBConnection, VistaDBDataAdapter>(query); // ~3700ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());