带有列名的DataReader到.CSV

我正在从SqlDataReader生成一个csv文件,但它没有写出列名,我怎么能让它写出来? 我正在使用的代码如下:

SqlConnection conn = new SqlConnection(myconn); SqlCommand cmd = new SqlCommand("dbo.test", conn); cmd.CommandType = CommandType.StoredProcedure; conn.Open(); SqlDataReader reader = cmd.ExecuteReader(); StringBuilder sb = new StringBuilder(); StreamWriter sw = new StreamWriter(myfilePath + "testfile.csv"); while (reader.Read()) { for (int i = 0; i < reader.FieldCount; i++) { string value = reader[i].ToString(); if (value.Contains(",")) value = "\"" + value + "\""; sb.Append(value.Replace(Environment.NewLine, " ") + ","); } sb.Length--; // Remove the last comma sb.AppendLine(); } conn.Close(); sw.Write(sb.ToString()); sw.Close(); 

读取所有列名称并将其附加到sb然后迭代读取器。

 SqlDataReader reader = cmd.ExecuteReader(); StringBuilder sb = new StringBuilder(); //Get All column var columnNames = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName) //OR .Select("\""+ reader.GetName"\"") .ToList(); //Create headers sb.Append(string.Join(",", columnNames)); //Append Line sb.AppendLine(); while (reader.Read()) .... 

我开发了以下高性能扩展

 static void Main(string[] args) { SqlConnection sqlCon = new SqlConnection("Removed"); sqlCon.Open(); SqlCommand sqlCmd = new SqlCommand("Select * from Table", sqlCon); SqlDataReader reader = sqlCmd.ExecuteReader(); string csv=reader.ToCSVHighPerformance(true); File.WriteAllText("Test.CSV", csv); reader.Close(); sqlCon.Close(); } 

Extention:

 public static string ToCSVHighPerformance(this IDataReader dataReader, bool includeHeaderAsFirstRow = true, string separator = ",") { DataTable dataTable = new DataTable(); StringBuilder csvRows = new StringBuilder(); string row = ""; int columns ; try { dataTable.Load(dataReader); columns= dataTable.Columns.Count; //Create Header if (includeHeaderAsFirstRow) { for (int index = 0; index < columns; index++) { row += (dataTable.Columns[index]); if (index < columns - 1) row += (separator); } row += (Environment.NewLine); } csvRows.Append(row); //Create Rows for (int rowIndex = 0; rowIndex < dataTable.Rows.Count; rowIndex++) { row = ""; //Row for (int index = 0; index < columns - 1; index++) { string value = dataTable.Rows[rowIndex][index].ToString(); //If type of field is string if (dataTable.Rows[rowIndex][index] is string) { //If double quotes are used in value, ensure each are replaced by double quotes. if (value.IndexOf("\"") >= 0) value = value.Replace("\"", "\"\""); //If separtor are is in value, ensure it is put in double quotes. if (value.IndexOf(separator) >= 0) value = "\"" + value + "\""; //If string contain new line character while (value.Contains("\r")) { value = value.Replace("\r", ""); } while (value.Contains("\n")) { value = value.Replace("\n", ""); } } row += value; if (index < columns - 1) row += separator; } dataTable.Rows[rowIndex][columns - 1].ToString().ToString().Replace(separator, " "); row += Environment.NewLine; csvRows.Append(row); } } catch (Exception ex) { throw ex; } return csvRows.ToString(); } 

使用此解决方案我创建了一个扩展。

 ///  /// ///  ///  ///  /// if null/empty will use IO.Path.GetTempPath() /// will use csv by default public static void ToCsv(this IDataReader reader, string filename, string path = null, string extension = "csv") { int nextResult = 0; do { var filePath = Path.Combine(string.IsNullOrEmpty(path) ? Path.GetTempPath() : path, string.Format("{0}.{1}", filename, extension)); using (StreamWriter writer = new StreamWriter(filePath)) { writer.WriteLine(string.Join(",", Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList())); int count = 0; while (reader.Read()) { writer.WriteLine(string.Join(",", Enumerable.Range(0, reader.FieldCount).Select(reader.GetValue).ToList())); if (++count % 100 == 0) { writer.Flush(); } } } filename = string.Format("{0}-{1}", filename, ++nextResult); } while (reader.NextResult()); } 

您可以使用SqlDataReader.GetName方法获取列的名称,如下所示:

 for(int i = 0; i < reader.FieldCount; i++) { string columnName = reader.GetName(i); } 

您可以使用SqlDataReader.GetName获取列名称

 for (int i = 0; i < reader.FieldCount; i++) { string columnName = reader.GetName(i); } 

您还可以创建如下的扩展方法:

 public static List ToCSV(this IDataReader dataReader, bool includeHeaderAsFirstRow, string separator) { List csvRows = new List(); StringBuilder sb = null; if (includeHeaderAsFirstRow) { sb = new StringBuilder(); for (int index = 0; index < dataReader.FieldCount; index++) { if (dataReader.GetName(index) != null) sb.Append(dataReader.GetName(index)); if (index < dataReader.FieldCount - 1) sb.Append(separator); } csvRows.Add(sb.ToString()); } while (dataReader.Read()) { sb = new StringBuilder(); for (int index = 0; index < dataReader.FieldCount - 1; index++) { if (!dataReader.IsDBNull(index)) { string value = dataReader.GetValue(index).ToString(); if (dataReader.GetFieldType(index) == typeof(String)) { //If double quotes are used in value, ensure each are replaced but 2. if (value.IndexOf("\"") >= 0) value = value.Replace("\"", "\"\""); //If separtor are is in value, ensure it is put in double quotes. if (value.IndexOf(separator) >= 0) value = "\"" + value + "\""; } sb.Append(value); } if (index < dataReader.FieldCount - 1) sb.Append(separator); } if (!dataReader.IsDBNull(dataReader.FieldCount - 1)) sb.Append(dataReader.GetValue(dataReader.FieldCount - 1).ToString().Replace(separator, " ")); csvRows.Add(sb.ToString()); } dataReader.Close(); sb = null; return csvRows; } 

例:

 List rows = null; using (SqlDataReader dataReader = command.ExecuteReader()) { rows = dataReader.ToCSV(includeHeadersAsFirstRow, separator); dataReader.Close(); }