有没有比DataTable.Load(DataReader)更快/更智能的方法来填充datatable?C#

4
我正在进行一些研究,以更好地了解SQL和使用DataTables。因此,我试图努力实现从MS SQL数据库读取数据并加载到datagridview中的良好性能。
我创建了一个SQL函数,并从我的工具中调用它,将结果加载到datatable中。如果我在SSMS中执行此函数,需要11-12秒才能加载结果(几乎有150万条记录),但是如果我使用编码的工具执行此函数,则需要超过30秒(仅用于执行DataTable.Load(SqlDataReader))。
到目前为止,我所做的是:
    private DataTable GetDataFromDB(string userId, string docId, DateTimeOffset date)
    {            
        string cmd = String.Format("select * from dbo.GetData(@userId, @docId, @dueDate);");

        using (SqlConnection conn = new SqlConnection(connectionString))
        {
            if (conn.State != ConnectionState.Open)
                conn.Open();

            SqlCommand command = new SqlCommand(cmd, conn);

            if (String.IsNullOrEmpty(userId))
                command.Parameters.AddWithValue("@userId", DBNull.Value);
            else
                command.Parameters.AddWithValue("@userId", userId);

            if (String.IsNullOrEmpty(docId))
                command.Parameters.AddWithValue("@docId", DBNull.Value);
            else
                command.Parameters.AddWithValue("@docId", docId);
            command.Parameters.AddWithValue("@dueDate", dueDate);

            SqlDataReader reader = command.ExecuteReader();

            stopWatch.Reset();
            stopWatch.Start();

            table.BeginLoadData();
            table.Load(reader, LoadOption.Upsert);
            table.EndLoadData();
            stopWatch.Stop();
            reader.Close();
            reader.Dispose();
            conn.Close();
        }

        return table;
    }

我已经进行了一些谷歌研究,这是我能找到的最好的结果。到目前为止,它运行得很好,但我想知道是否有可能更快地获取结果。有什么建议吗? 此外,我有一个内存问题。一旦我开始调用,工具将分配高达900MB的RAM,直到它获得所有条目。我已经设法在每次调用上面的函数时释放内存,但我认为,900MB相当多,并且另一个问题是,它不会释放所有所需的RAM。例如:当我启动工具时,它需要大约7MB的RAM,如果我第一次调用上面的方法,它将需要900MB。如果我再次调用它,它将释放大部分内存,但仍需要930MB。第三次960MB,依此类推。因此,每次调用它都会分配更多的内存,这将导致“系统内存不足”异常,如果此方法经常被调用。
非常感谢!

1
一个 DataGridView 控件表明 OP 正在处理桌面应用程序而不是 Web 应用程序。 - Steve
2
DataTable非常低效,因为它需要尽可能通用--每个值都存储为Object,每行都存储为Object数组。一般来说,更聪明的使用DataTable的方法是根本不使用它。直接从SqlDataReader初始化对象--这需要更多的代码,不太方便,但可以节省大量内存和速度。在数据网格的特定情况下,您需要查看使它们虚拟化,以便不必始终存在所有数据。 - Jeroen Mostert
1
你有看过DataTable.Fill()方法吗?另外,与其使用Select * from Query的方式,其中只涉及3列数据,为什么不将查询改为只选择那3列,并添加一个更明确的筛选语句来定义Where子句? - MethodMan
@MethodMan 我没有DataTable.Fill方法。而且查询也没有返回3列。我正在调用SQL函数,我已经创建并给它了3个参数,你可以在查询中看到。它返回9列。@Jeroen Mostert 谢谢,我会去看看的。 - Echelon
非常有效,谢谢伙计。 - tanvir
显示剩余3条评论
2个回答

1

性能将根据您加载的数据类型和数量而异。以下链接将为您提供具有性能报告的解决方案。尝试像这样使用您的方法并比较性能。

希望这可以帮助您。

填充数据表的最快方法


链接太棒了!非常感谢! - Echelon

0

对我来说,使用 DataTable.Load(SqlDataReader) 是最快的方式

        DataTable dt = new DataTable();
        using (var con = new SqlConnection { ConnectionString = "ConnectionString" })
        {
            using (var command = new SqlCommand { Connection = con })
            {
                con.Open();
                command.CommandText = @"SELECT statement.....";
                command.Parameters.AddWithValue("@param", "Param");
                //load the into DataTable
                dt.Load(command.ExecuteReader(), LoadOption.Upsert);
            }// this will dispose command

        }// this will dispose and close connection

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