【问题标题】:Is there a faster/smarter way, to fill a datatable than DataTable.Load(DataReader)? C#有没有比 DataTable.Load(DataReader) 更快/更智能的方法来填充数据表? C#
【发布时间】:2016-06-06 13:21:33
【问题描述】:

我正在做一些研究,以更好地理解 SQL 和使用 DataTables。 所以我试图从 MS SQL 数据库读取数据并将其加载到 datagridview 中。

我创建了一个 SQL 函数,我从我的工具中调用它并将结果加载到数据表中。 如果我在 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以此类推。因此,每次调用都会分配更多内存,如果经常调用此方法,则会导致“系统内存不足”异常。

非常感谢!

【问题讨论】:

  • 您是在谈论包含 ASP.NET 服务器端包的datatables.net jQuery 插件吗?还是您的意思是不同的数据表?
  • DataGridView 控件表明 OP 正在使用桌面应用程序而不是 Web 应用程序
  • 哦,不好意思,不知道,还有一个插件,同名。我说的是 System.Data.DataTable。我希望,我确实正确理解了您的问题...
  • DataTable 效率极低,因为它需要尽可能通用——每个值都存储为Object,每一行都存储为Objects 的数组。一般来说,使用DataTable 的更聪明的方法是根本不使用它。直接从SqlDataReader 初始化你的对象——这是更多的代码并且不那么方便,但它节省了内存并加速了一些激烈的事情。在数据网格的特定情况下,您需要考虑将它们虚拟化,这样就不必一直存在所有数据。
  • 你看过DataTable.Fill() 方法吗.. 也不要使用Select * from Query,你只需要处理 3 列,为什么不将查询更改为选择只有这 3 列添加了更明确的过滤语句,这意味着您的 Where Clause?

标签: c# datatable sqldatareader


【解决方案1】:

性能会因您加载的数据内容和数量而异。 下面的链接将为您提供性能报告的解决方案。用你的方法尝试这样的事情并比较性能。

希望这会对你有所帮助。

Fastest way to populate datatable

【讨论】:

  • 链接是黄金!非常感谢!
【解决方案2】:

对我来说使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 2019-10-17
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多