【问题标题】:Dumping SQL table to .csv C#将 SQL 表转储到 .csv C#
【发布时间】:2016-08-11 16:52:38
【问题描述】:

我正在尝试在我的应用程序中实现一个脚本,该脚本将转储一个 sql db(正在运行ms sql server express 2014) 到 .csv 文件。

这是我目前写的代码:

        public void doCsvWrite(string timeStamp){       
        try {
            //specify file name of log file (csv).
            string newFileName = "C:/TestDirectory/DataExport-" + timeStamp + ".csv";
            //check to see if file exists, if not create an empty file with the specified file name.
            if (!File.Exists(newFileName)) {
                FileStream fs = new FileStream(newFileName, FileMode.CreateNew);
                fs.Close();
                //define header of new file, and write header to file.
                string csvHeader = "ITEM1,ITEM2,ITEM3,ITEM4,ITEM5";
                using (FileStream fsWHT = new FileStream(newFileName, FileMode.Append, FileAccess.Write))
                using(StreamWriter swT = new StreamWriter(fsWHT))
                {
                    swT.WriteLine(csvHeader.ToString());
                }
            }
            //set up connection to database.
            SqlConnection myDEConnection;   
            String cDEString = "Data Source=localhost\\NAMEDPIPE;Initial Catalog=db;User Id=user;Password=pwd";
            String strDEStatement = "SELECT * FROM table"; 

            try
            {
                myDEConnection = new SqlConnection(cDEString);
            }
            catch (Exception ex)
            {  
                //error handling here.
                return;
            }

            try
            {
                myDEConnection.Open();
            }
            catch (Exception ex)
            {
                //error handling here.
                return;
            }
            SqlDataReader reader = null;
            SqlCommand myDECommand = new SqlCommand(strDEStatement, myDEConnection);
            try
            {
                reader = myDECommand.ExecuteReader();
                while (reader.Read())
                {
                    for (int i = 0; i < reader.FieldCount; i++)
                    {
                        if(reader["Column1"].ToString() == "") {
                            //does nothing if the current line is "bugged" (containing no values at all, typically happens after reboot of 3rd party equipment).
                        }
                        else {
                            //grab relevant tag data and set the csv line for the current row.
                            string csvDetails = reader["Column1"] + "," + reader["Column2"] + "," + String.Format("{0:0.0}", reader["Column3"]) + "," + String.Format("{0:0.000}", reader["Column4"]) + "," + reader["Column5"];

                            using (FileStream fsWDT = new FileStream(newFileName, FileMode.Append, FileAccess.Write))
                            using(StreamWriter swDT = new StreamWriter(fsWDT))
                            {
                                //write csv line to file.
                                swDT.WriteLine(csvDetails.ToString());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //error handling here.
                myDEConnection.Close();
                return;
            }
            myDEConnection.Close();
        }
        catch (Exception ex)
        {
            //error handling here.
            MessageBox.Show(ex.Message);
        }
    }

现在,当我将它与基于 SQLite 的第 3 方数据库一起使用时,它运行良好,但是在将它修改为我的 MSSQL 数据库后得到的输出看起来像这样(ITEM1 是主键,一个标准自增 ID 字段):

ITEM1,ITEM2,ITEM3,ITEM4,ITEM5
1,row1_item2,row1_item3,row1_item4,row1_item5
1,row1_item2,row1_item3,row1_item4,row1_item5
1,row1_item2,row1_item3,row1_item4,row1_item5
1,row1_item2,row1_item3,row1_item4,row1_item5
1,row1_item2,row1_item3,row1_item4,row1_item5
1,row1_item2,row1_item3,row1_item4,row1_item5
2,row2_item2,row2_item3,row2_item4,row2_item5
2,row2_item2,row2_item3,row2_item4,row2_item5
2,row2_item2,row2_item3,row2_item4,row2_item5
2,row2_item2,row2_item3,row2_item4,row2_item5
2,row2_item2,row2_item3,row2_item4,row2_item5
3,row3_item2,row3_item3,row3_item4,row3_item5
3,row3_item2,row3_item3,row3_item4,row3_item5
3,row3_item2,row3_item3,row3_item4,row3_item5
3,row3_item2,row3_item3,row3_item4,row3_item5
....

所以它似乎写了同一行的几个条目,我只想每行一行。有什么建议吗?

提前致谢。

编辑:感谢大家的回答!

【问题讨论】:

  • 我认为你的 using(StreamWriter swDT = new StreamWriter(fsWDT)) { //将 csv 行写入文件。 swDT.WriteLine(csvDetails.ToString()); } 行需要位于你的 for 循环之外。如果我是对的,for 循环应该计算出要写入的列,但是您已经硬写了这些。在您的 for 循环中构建该行,然后在此循环之外写出结果。
  • 打开和关闭文件流是昂贵的操作。不要在每次迭代时都这样做。在开始时打开流一次,仅在最后关闭。

标签: c# sql .net sql-server csv


【解决方案1】:

下面的部分不需要 for 循环。因为它从 0 循环到 FieldCount,我假设循环最初是为了将每一列中的文本附加在一起,但在循环内部有一行连接文本并将其分配给 csvDetails。

        try
        {
            reader = myDECommand.ExecuteReader();
            while (reader.Read())
            {
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    if(reader["Column1"].ToString() == "") {
                        //does nothing if the current line is "bugged" (containing no values at all, typically happens after reboot of 3rd party equipment).
                    }
                    else {
                        //grab relevant tag data and set the csv line for the current row.
                        string csvDetails = reader["Column1"] + "," + reader["Column2"] + "," + String.Format("{0:0.0}", reader["Column3"]) + "," + String.Format("{0:0.000}", reader["Column4"]) + "," + reader["Column5"];

                        using (FileStream fsWDT = new FileStream(newFileName, FileMode.Append, FileAccess.Write))
                        using(StreamWriter swDT = new StreamWriter(fsWDT))
                        {
                            //write csv line to file.
                            swDT.WriteLine(csvDetails.ToString());
                        }
                    }
                }
            }
        }

【讨论】:

  • 谢谢!我从另一个我写的 sn-p 读取 SQL 部分来获取所有列数据,而不仅仅是指定的数据。似乎这让我失去了理智。再次感谢!
【解决方案2】:

通常,我们使用专门设计的导出/导入实用程序来转储数据。 但是,如果您必须实现自己的例程,我建议分解

private static IEnumerable<IDataRecord> SourceData(String sql) {
  using (SqlConnection con = new SqlConnection(ConnectionStringHere)) {
    con.Open();

    using (SqlCommand q = new SqlCommand(sql, con)) {
      using (var reader = q.ExecuteReader()) {
        while (reader.Read()) {
          //TODO: you may want to add additional conditions here

          yield return reader; 
        }
      }
    }
  }
}

private static IEnumerable<String> ToCsv(IEnumerable<IDataRecord> data) {
  foreach (IDataRecord record in data) {
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < record .FieldCount; ++i) {
      String chunk = Convert.ToString(record .GetValue(0));

      if (i > 0)
        sb.Append(','); 

      if (chunk.Contains(',') || chunk.Contains(';'))
        chunk = "\"" + chunk.Replace("\"", "\"\"") +  "\"";

      sb.Append(chunk);
    }

    yield return sb.ToString(); 
  } 
}

拥有SourceDataToCsv,您可以轻松实现

private static void WriteMyCsv(String fileName) {
  var source = SourceData("SELECT * FROM table");

  File.WriteAllLines(fileName, ToCsv(source));
}

【讨论】:

    【解决方案3】:

    你有一个循环遍历字段计数的 for 循环。

    for (int i = 0; i < reader.FieldCount; i++)
    

    我认为如果您删除循环,它会起作用,因为您不需要遍历列。

    【讨论】:

      【解决方案4】:

      这是因为输出放置在 for 循环中

      for (int i = 0; i < reader.FieldCount; i++)
      

      每条记录都会重复 FieldCount 次

      【讨论】:

        猜你喜欢
        • 2012-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-05
        • 1970-01-01
        • 2012-08-05
        相关资源
        最近更新 更多