使用c#中的select语句动态创建CSV文件

时间:2017-02-21 11:23:22

标签: c# mysql csv

我有一个网站,允许用户使用特定搜索条件(国家/地区和日期)将数据下载到CSV文件。他们从下拉列表和JQuery日期选择器中选择所有信息。

导出适用于小型数据集,但只要您尝试下载10000行数据,就需要很长时间,甚至可能超时!

我已尝试过不同的方法,但由于此项目的时间限制,我想坚持使用此方法。

我的代码如下:

        using (SqlConnection con = new SqlConnection(cs))
        {

            if (country.Contains("GB"))
            {
                using (SqlCommand cmd = new SqlCommand("SELECT * from " + logData + " where country in ('GB') and close_date between '" + fromDate + "' and '" + toDate + "'"))
                {
                    using (SqlDataAdapter sda = new SqlDataAdapter())
                    {
                        cmd.Connection = con;
                        sda.SelectCommand = cmd;
                        using (DataTable dt = new DataTable())
                        {
                            sda.Fill(dt);

                            //Build the CSV file data as a Comma separated string.
                            string csv = string.Empty;

                            foreach (DataColumn column in dt.Columns)
                            {
                                //Add the Header row for CSV file.
                                csv += column.ColumnName + ',';
                            }
                            //Console.Write(cmd);
                            //Add new line.
                            csv += "\r\n";

                            foreach (DataRow row in dt.Rows)
                            {
                                foreach (DataColumn column in dt.Columns)
                                {
                                    //Add the Data rows.
                                    //Response.Write(row[column.ColumnName].ToString().Replace(",", ";") + ',');
                                      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=data.csv");
                            Response.Charset = "";
                            Response.ContentType = "application/text";
                            Response.Output.Write(csv);
                            Response.Flush();
                            Response.End();
                        }
                    }
                }


            }
  

Response.Write(row [column.ColumnName] .ToString()。Replace(",",";")+',' );

     

csv + = row [column.ColumnName] .ToString()。替换(",",";")+',&#39 ;;

如果我使用 Response.Write ...,文件下载速度 MUCH 更快,但数据全部在一行而且不包含标题。 CSV + =行...慢得多,偶尔会超时

如果我要使用Response.Write并包含标题,如何将数据分成多行?

实际的SQL查询需要2秒才能运行并生成12231条记录

2 个答案:

答案 0 :(得分:4)

是的,字符串连接非常慢,因为C#中的字符串是不可变的。我建议你使用StringBuilder类(https://msdn.microsoft.com/en-us/library/system.text.stringbuilder(v=vs.110).aspx)来构造你的字符串。

答案 1 :(得分:2)

看起来你试图将整个结果集(来自SELECT)保存在RAM中两次。不要忘记SQL的重点基本上是让你使用比你拥有的任何RAM都大的数据集。这并不意味着你必须这样做,但它确实意味着你在设计软件时应该“一次一行”。

无论如何,你将整个结果集加载到RAM中,两次。

一次因为你使用SqlDataAdapter而不是SqlDataReader来检索数据。 SqlDataReader一次拉取一行数据。

再次,因为您试图将整个输出放入单个文本字符串中。这很糟糕(a)因为它需要大量的RAM,而且 (b)因为str = str+whatever必须复制字符串,删除旧字符串并存储新字符串。所以

 string str = null;
 foreach (item in someLargeCollection) str = str + item;

以O(n平方)时间运行。当n(集合的大小)大于几百项时,看起来像是超时。

所以,快速修复:

     foreach (DataRow row in dt.Rows)
     {
         foreach (DataColumn column in dt.Columns)
         {
             csv += row[column.ColumnName].ToString().Replace(",", ";") + ',';
         }
         csv += "\r\n";
         Response.Write(csv);
         csv = null;
     }

这会写出每一行,使csv不会太大,并解决第二个问题。

StringBuilder修复...构建字符串的正确方法:

     foreach (DataRow row in dt.Rows)
     {
         StringBuilder csv = new StringBuilder();
         foreach (DataColumn column in dt.Columns)
         {
             csv.Append(row[column.ColumnName].ToString().Replace(",", ";") + ',');
         }
         csv.AppendLine();
         Response.Write(csv.ToString());
     }

StringBuilder在创建文本字符串时会破坏O(n平方)问题。

最后,您应该查找SqlDataReader类。