首页 > 解决方案 > 将 16k 行的表数据写入文件超时

问题描述

我的网站上有一个功能,管理员可以下载表格的内容。该表大约有 16ks,只有 8 列。

这是我的 C# 代码

using (MySqlConnection con = new MySqlConnection(constr))
        {

            string query = "SELECT * from wp_portal_users";
            using (MySqlCommand cmd = new MySqlCommand(query))
            {

                cmd.Connection = con;
                con.Open();

                MySqlDataReader sdr = cmd.ExecuteReader();
                DataTable dt = new DataTable();
                if (sdr.HasRows == true)
                {
                    dt.Columns.Add("sysproID");
                    dt.Columns.Add("password");
                    dt.Columns.Add("username");
                    dt.Columns.Add("update_time", typeof(string));
                    dt.Columns.Add("tempPasswordValidity");
                    dt.Columns.Add("tempPassword");
                    dt.Columns.Add("last_login");
                    dt.Columns.Add("login_count");
                    dt.Rows.Add("Syspro ID", "Password", "Username", "Last Updated", "Temp Password Validity", "Temp Password", "Last Login", "Login Count");
                    DataRow dr = null;

                    while (sdr.Read())
                    {
                        dr = dt.NewRow();
                        dr["sysproID"] = sdr["sysproID"].ToString();
                        dr["password"] = sdr["password"].ToString();
                        dr["username"] = sdr["username"].ToString();
                        dr["update_time"] = sdr["update_time"].ToString();
                        dr["tempPasswordValidity"] = sdr["tempPasswordValidity"].ToString();
                        dr["tempPassword"] = sdr["tempPassword"].ToString();
                        dr["last_login"] = sdr["last_login"].ToString();
                        dr["login_count"] = sdr["login_count"].ToString();
                        dt.Rows.Add(dr);
                    }
                }

                string csv = string.Empty;

                foreach (DataRow row in dt.Rows)
                {
                    foreach (DataColumn column in dt.Columns)
                    {
                        //Add the Data rows.
                        csv += row[column.ColumnName].ToString().Replace(",", ";") + ',';
                    }

                    //Add new line.
                    csv += "\r\n";
                }

                //Download the CSV file.
                Response.Clear();
                Response.Buffer = true;
                Response.AddHeader("content-disposition", "attachment;filename=PortalUsers.csv");
                Response.Charset = "";
                Response.ContentType = "application/text";
                Response.Output.Write(csv);
                Response.Flush();
                Response.End();
            }

        }

当它在只有几行的表上运行时,它运行良好。有 16k 行时,它会超时。我可以改变什么来纠正这个性能问题?

标签: c#asp.netdatatable

解决方案


您不应该在内存中构建数据表只是为了遍历行(然后将其丢弃)。手动构建数据表相当慢。

而是使用您的 MySqlDataReader 将列字符串添加到您的变量中。

像这样的东西:

            if (sdr.HasRows == true)
            {
                string csv = string.Empty;

                while (sdr.Read())
                {
                    csv += sdr["sysproID"].ToString().Replace(",", ";") + ',';
                    // add other columns

                    csv += "\r\n";
                }
            }
            //Download the CSV file.

编辑

正如@John 在评论中提到的,您应该使用 StringBuilder 来构建 csv:

            if (sdr.HasRows == true)
            {
                StringBuilder sb = new StringBuilder();

                while (sdr.Read())
                {
                    sb.Append(sdr["sysproID"].ToString().Replace(",", ";"));
                    sb.Append(";");
                    // add other columns

                    sb.AppendLine();
                }
            }
            //Download the CSV file.

推荐阅读