c#从SQL查询生成非常大的文本文件

本文关键字:文本 文件 非常 SQL 查询 | 更新日期: 2023-09-27 18:06:25

我从SQL数据库中获取100+表,并将所有数据写入1个文件。在SQL中,我运行了一个复杂的查询,将这些表格式化为一个视图。在VS中,我连接到SQL并从视图中选择*,并使用字符串生成器来构建文件。

如果我只抓取5%的数据,如果我试图抓取100%的内存异常,这会起作用。该视图有超过1000万条记录。我在寻求建议。谢谢。

string cs4 = ConfigurationManager.ConnectionStrings["example"].ConnectionString;
StringBuilder sb4 = new StringBuilder();
using (SqlConnection con4 = new SqlConnection(cs4))
{
    string strTQuery = @"SELECT * FROM [dbo].[view]";
    SqlDataAdapter da4 = new SqlDataAdapter(strTQuery, con4);
    DataSet ds4 = new DataSet();
    da4.Fill(ds4);
    ds4.Tables[0].TableName = "Example";
    foreach (DataRow exDR in ds4.Tables["Example"].Rows)
    {
        sb4.Append(exDR["A"].ToString() + strDelimiter);
        sb4.Append(exDR["B"].ToString() + strDelimiter);
        sb4.Append(exDR["C"].ToString() + strDelimiter);
        sb4.Append(exDR["D"].ToString());
        sb4.Append("'r'n");
    }
}
StreamWriter file4 = new StreamWriter(@"''Desktop" + todaysDate + ".csv");
file4.WriteLine(sb4.ToString());
file4.Close();

c#从SQL查询生成非常大的文本文件

正如D Stanley所提到的,您需要在读取的同时写入,因此所有内容都直接到磁盘,而不是先到内存然后到磁盘。这样就可以了。

string cs4 = ConfigurationManager.ConnectionStrings["example"].ConnectionString;
using (SqlConnection con4 = new SqlConnection(cs4))
using(StreamWriter file4 = new StreamWriter(@"''Desktop" + todaysDate + ".csv"))
{
    string strTQuery = @"SELECT A, B, C, D FROM [dbo].[view]";
    var command = new SqlCommand(strTQuery, con4);
    con4.Open();
    var reader = command.ExecuteReader();
    while(reader.Read())
    {
        file4.Write(reader.GetString(0) + strDelimiter);
        file4.Write(reader.GetString(1) + strDelimiter);
        file4.Write(reader.GetString(2) + strDelimiter);
        file4.Write(reader.GetString(3));
        file4.Write("'r'n");
    }
}

您还应该使用SqlDataReader而不是DataSet,因为这是一个向前移动的指针,并在每次迭代中检索结果。

您试图将整个文件存储在运行时内存中,这就是您获得内存错误的原因。尝试保存文件块并修改文件。

string cs4 = ConfigurationManager.ConnectionStrings["example"].ConnectionString;
            StringBuilder sb4 = new StringBuilder();
            using (SqlConnection con4 = new SqlConnection(cs4))
            {
                StreamWriter file4 = new StreamWriter(@"''Desktop" + todaysDate + ".csv", true);
                string strTQuery = @"SELECT * FROM [dbo].[view]";
                SqlDataAdapter da4 = new SqlDataAdapter(strTQuery, con4);
                DataSet ds4 = new DataSet();
                da4.Fill(ds4);
                ds4.Tables[0].TableName = "Example";
                foreach (DataRow exDR in ds4.Tables["Example"].Rows)
                {
                    sb4 = new StringBuilder();
                    sb4.Append(exDR["A"].ToString() + strDelimiter);
                    sb4.Append(exDR["B"].ToString() + strDelimiter);
                    sb4.Append(exDR["C"].ToString() + strDelimiter);
                    sb4.Append(exDR["D"].ToString());
                    sb4.Append("'r'n");
                    file4.WriteLine(sb4.ToString());
                }
                file4.Close();
            }

问题在这一行:

file4.WriteLine(sb4.ToString());

原因是CLR中的对象不能大于2GB。在这种情况下,你的字符串特别大,甚至不需要这样的行为(我的意思是ToString)。为避免此问题,请在收到数据时使用FileStream写入数据。