带有列名的DataReader到.CSV

Use*_*er0 11 c# sql-server

我正在从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();
Run Code Online (Sandbox Code Playgroud)

Sat*_*pal 9

读取所有列名称并将其附加到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())
....
Run Code Online (Sandbox Code Playgroud)


SiD*_*SiD 5

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

for (int i = 0; i < reader.FieldCount; i++)
{
    string columnName = reader.GetName(i);
}
Run Code Online (Sandbox Code Playgroud)

您还可以创建一个扩展方法,如下所示:

public static List<string> ToCSV(this IDataReader dataReader, bool includeHeaderAsFirstRow, string separator)
{
    List<string> csvRows = new List<string>();
    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;
}
Run Code Online (Sandbox Code Playgroud)

例子:

List<string> rows = null;
using (SqlDataReader dataReader = command.ExecuteReader())
    {
        rows = dataReader.ToCSV(includeHeadersAsFirstRow, separator);
        dataReader.Close();
    }
Run Code Online (Sandbox Code Playgroud)


sur*_*rya 5

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

/// <summary>
/// 
/// </summary>
/// <param name="reader"></param>
/// <param name="filename"></param>
/// <param name="path">if null/empty will use IO.Path.GetTempPath()</param>
/// <param name="extension">will use csv by default</param>
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());
}
Run Code Online (Sandbox Code Playgroud)