SqlDataReader和SqlDataAdapter:哪一个在返回DataTable时性能更好?

29

我想知道在返回 DataTable 方面哪个的性能更好。在这里,我使用 DataTable.Load(dr) 来处理 SqlDataReader

使用 SqlDataReader

public static DataTable populateUsingDataReader(string myQuery)
{
    DataTable dt = new DataTable();
    using (SqlConnection con = new SqlConnection(constring))
    {
        SqlCommand cmd = new SqlCommand(myQuery, con);
        con.Open();
        SqlDataReader dr = null;
        dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
        if (dr.HasRows)
        {
            dt.Load(dr);
        }
        return dt;
    }
}

使用 SqlDataAdapter

public DataTable populateUsingDataAdapter(string myQuery)
{
    SqlDataAdapter dap = new SqlDataAdapter(myQuery,cn);
    DataSet ds = new DataSet();
    dap.Fill(ds);
    return ds.Tables[0];
}

3
为什么不直接记录开始时间,循环运行X次,然后记录结束时间呢? - Daveo
@Satinder Singh 不是与问题相关,但是:在DataReader版本中,不要忘记将SqlCommand和DataReader变量放入using块中,因为它们是可释放的。 - Richardissimo
如果你只处理一个表格,也许直接调用 DataTable.Load() 就足够了。 - Brain2000
5个回答

28
差别可以忽略不计,因此最好使用更简洁的版本:SqlDataAdapter.FillSqlDataReader.Fill 内部创建一个名为 LoadAdapter 的类(从 DataAdapter 派生),并调用其 Fill 方法:性能将非常类似于 SqlDataAdapter.Fill(DataTable)
在初始化/验证参数方面可能会有一些小差异,但随着行数的增加,这些差异将变得越来越不显著。
还要注意,您的第二个示例应进行修改,以与第一个示例相比较。
public DataTable populateUsingDataAdapter(string myQuery)
{
    using (SqlConnection con = new SqlConnection(constring))
    {
        SqlDataAdapter dap = new SqlDataAdapter(myQuery,con);
        DataTable dt = new DataTable();
        dap.Fill(dt);
        return dt;
    }
}

+1 - 因为我刚刚写了同样的东西(记录一下,直到我写完之后才看到你的答案)。 - Tim M.
@joe:谢谢您的回复,如果我没错的话,在这种情况下SqlDataAdapter会是一个不错的选择。 - Satinder singh
@Joe这里返回的dt是null,对吧? - Behzad
2
SQLDataReader和SQLDataAdapter之间的差异真的可以忽略不计吗?您有任何展示差异的基准测试吗?如下回复所指出的那样,从DBDataReader读取数据的最快方法可能包含一个基准测试。此外,这篇关于DataAdapter和DataReader的MSDN文章可能会有用。 - surfmuggle
我知道这个线程很旧了,只是想为解决方案添砖加瓦:像所有东西一样,我建议测试您的用例,我留下一个LinqPad脚本进行测试,对我来说DataAdapter更好,因为它允许您将主键映射到DataTable中。下载LinqPad脚本 - Gabriel Espinoza

8
这个问题,更具体地说,这个答案表明你的第二个示例更快。虽然它并不是详尽的基准测试,但确实是一个有趣的测试。
反射 DataTable 的源代码显示,调用 DataTable.Load() 实际上创建了一个名为 LoadAdapter 的内部 DataAdapter 子类,并调用了 DataAdapterFill() 方法。 SqlDataAdapter 在完全相同的位置完成大部分加载工作。
更重要的是,我倾向于选择第二个示例,因为它更易读。两个示例都无法与直接使用 DataReader 提供的快速访问相比,因此我会选择更清洁的代码。

5

SqlDataReader 的速度历来比 SqlDataAdapter 快得多。虽然在 .NET 4.5 中可能已经进行了改进,但我怀疑它是否已经提高到超越 DataReader 的性能。


3
不是真的。直接从 SqlDataReader 处理数据可能比将整个结果集加载到 DataTable 中更快,但这比较的是不同的事物。对于填充 DataTable,两者的性能相似。 - Joe
3
您是正确的。我假设使用一个读取器来填充一个自定义类,而不是填充一个“DataTable”。如果结果必须是一个“DataTable”,那么无论使用适配器还是读取器,性能都会同样差。 - Rob Epstein

0

SqlDataReader比SQlDataAdapter更快,因为它在连接状态下工作,这意味着只要查询结果可用,就会立即返回第一个结果..


我也知道这个理论部分。我想知道上面的代码哪一个更快。 - Satinder singh
@Satindersingh 对不起,我以为你在问区别..SqlDatareader 会更快,因为它在连接状态下工作,这意味着只要查询结果可用,第一个结果就会返回.. - coder
3
“SqlDataReader会比SqlDataAdapter快,因为它在连接状态下工作” - 这是不正确的:在两种情况下,都会在将结果返回给调用者之前完全填充DataTable。 - Joe

0

除了所选的解决方案,我想补充一点:

使用DataReader,您不需要知道您拥有哪种类型的DbConnection。

您只需要一个实现IDbConnection的实例,然后可以使用“connection.CreateCommand”,然后是“dbCommand.ExecuteReader”,最后是dataTable.Load。

但是当您使用DataAdapter时,您将需要知道使用了哪个连接(即oracle、sqlserver等)

(这与主题发起人无关,但我在使用g**gle搜索此主题时来到了这里。)


1
这是对Joe答案的评论。 - jogo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接