无法从SQL Server和C#应用程序下载600万到700万条包含80列csv的记录

无法从SQL Server和C#应用程序下载600万到700万条包含80列csv的记录,c#,sql,asp.net,sql-server,csv,C#,Sql,Asp.net,Sql Server,Csv,我需要从asp.net C#上创建的应用程序中下载一个摘录。它从SQL Server 2008读取数据,并尝试将其写入.csv文件。有600万到700万行,大约有80列。应用程序中断并停止响应,我无法通过web浏览器下载 作为替代方案,我尝试创建一个在服务器上运行的windows服务来提取数据并创建一个csv文件。但是,如果有多个下载请求,服务器就会耗尽内存,服务就会中断并停止工作 表中的总数据量为700 MB,若要读取此数据,服务器内存的利用率将达到5 GB,每个请求的利用率为8 GB。如果有

我需要从asp.net C#上创建的应用程序中下载一个摘录。它从SQL Server 2008读取数据,并尝试将其写入
.csv
文件。有600万到700万行,大约有80列。应用程序中断并停止响应,我无法通过web浏览器下载

作为替代方案,我尝试创建一个在服务器上运行的windows服务来提取数据并创建一个csv文件。但是,如果有多个下载请求,服务器就会耗尽内存,服务就会中断并停止工作

表中的总数据量为700 MB,若要读取此数据,服务器内存的利用率将达到5 GB,每个请求的利用率为8 GB。如果有多个异步请求,内存利用率将达到100%,服务将停止,并且不会生成文件

目前使用的数据表和数据行如下所示,需要一种使用C#application on request或任何其他方法下载数据的方法,该方法可以根据存储过程提供的数据生成csv文件

谢谢

// the method to extract data
public getdata( xyz ....)
{
    dbInstance = ConfigDBDAL.GetTransactionDBInstance(userDO);

    DbCommand dbCommand = dbInstance.GetStoredProcCommand(PR_GET_EXTRACTS);
    dbCommand.CommandTimeout = 0;

    // a few parameter passing like this
    DbParameter paramStartDate = new SqlParameter("@StartDate", typeof(DateTime));
    paramStartDate.Value = startDate;
    dbCommand.Parameters.Add(paramStartDate);

    DbParameter paramStartDate = new SqlParameter("@EndDate", typeof(DateTime));
    paramStartDate.Value = startDate;
    dbCommand.Parameters.Add(paramStartDate);

    // Creating a data table for the required 80 columns 
    datatable = new DataTable();

    datatable.Columns.Add("COL1");
    datatable.Columns.Add("COL2");
    datatable.Columns.Add("COL3");
    .
    .
    .
    datatable.Columns.Add("COL80");

    using (IDataReader reader = dbInstance.ExecuteReader(dbCommand))
    {
        DataRow newRow;

        while (reader.Read())
        {
            row = datatable.NewRow();
            row["COL1"] = reader["COL1"];
            row["COL2"] = reader["COL2"];
            .
            .
            row["COL80"] = reader["COL80"];

            datatable.Rows.Add(row);
        }
    }

    return datatable;
}

DataTable
类产生一些开销。尝试使用
StringBuilder
构建纯CSV字符串:

var sb = new StringBuilder();
sb.AppendLine("sep=,");
sb.AppendLine("COL1,COL2,COL3,...,COL-N"); // columns

using (IDataReader reader = dbInstance.ExecuteReader(dbCommand))
{
    DataRow newRow;
    while (reader.Read())
    {
        sb.Append((string)reader["COL1"] + ",");
        sb.Append((string)reader["COL2"] + ",");
        sb.Append((string)reader["COL3"] + ",");
        ...
        sb.Append((string)reader["COL-N"] + Environment.NewLine);
    }
}

return sb.ToString(); // returns string representing CSV file content

DataTable
类产生一些开销。尝试使用
StringBuilder
构建纯CSV字符串:

var sb = new StringBuilder();
sb.AppendLine("sep=,");
sb.AppendLine("COL1,COL2,COL3,...,COL-N"); // columns

using (IDataReader reader = dbInstance.ExecuteReader(dbCommand))
{
    DataRow newRow;
    while (reader.Read())
    {
        sb.Append((string)reader["COL1"] + ",");
        sb.Append((string)reader["COL2"] + ",");
        sb.Append((string)reader["COL3"] + ",");
        ...
        sb.Append((string)reader["COL-N"] + Environment.NewLine);
    }
}

return sb.ToString(); // returns string representing CSV file content

你也可以试试这个方法

public static void ExportPlantData(string channelId)
{
    string query = string.Empty;

    DataService dataService = new DataService();
    DbCommand dataCmd = null;
    DataTable contentToExport = new DataTable();

    try
    {
        query = "SELECT * from tablename";

        dataCmd = dataService.Database.GetSqlStringCommand(query);
        contentToExport = dataService.ExecuteDataTable(dataCmd);
        ExportToCSV(contentToExport);
    }    
}


public static void ExportToCSV(DataTable contentToexport)
{
    StringBuilder csvData = new StringBuilder();
    StringBuilder headers = new StringBuilder();

    foreach (DataRow row in contentToexport.Rows)
    {
        headers = string.Empty;
        foreach (DataColumn column in contentToexport.Columns)
        {
            csvData.Append(row[column].ToString() + ",");
            headers.Append(column.ColumnName + ",");
        }

       csvData.Append("\r\n");
       headers.Append("\r\n");
    }

    string contentToExport = headers.Append(csvData.ToString()).ToString();
    string attachment = "attachment; filename=export.csv";

    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.ClearHeaders();
    HttpContext.Current.Response.ClearContent();
    HttpContext.Current.Response.AddHeader("content-disposition", attachment);
    HttpContext.Current.Response.ContentType = "application/csv";
    HttpContext.Current.Response.AddHeader("Pragma", "public");
    HttpContext.Current.Response.Write(contentToExport);
    System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest();
}

你也可以试试这个方法

public static void ExportPlantData(string channelId)
{
    string query = string.Empty;

    DataService dataService = new DataService();
    DbCommand dataCmd = null;
    DataTable contentToExport = new DataTable();

    try
    {
        query = "SELECT * from tablename";

        dataCmd = dataService.Database.GetSqlStringCommand(query);
        contentToExport = dataService.ExecuteDataTable(dataCmd);
        ExportToCSV(contentToExport);
    }    
}


public static void ExportToCSV(DataTable contentToexport)
{
    StringBuilder csvData = new StringBuilder();
    StringBuilder headers = new StringBuilder();

    foreach (DataRow row in contentToexport.Rows)
    {
        headers = string.Empty;
        foreach (DataColumn column in contentToexport.Columns)
        {
            csvData.Append(row[column].ToString() + ",");
            headers.Append(column.ColumnName + ",");
        }

       csvData.Append("\r\n");
       headers.Append("\r\n");
    }

    string contentToExport = headers.Append(csvData.ToString()).ToString();
    string attachment = "attachment; filename=export.csv";

    HttpContext.Current.Response.Clear();
    HttpContext.Current.Response.ClearHeaders();
    HttpContext.Current.Response.ClearContent();
    HttpContext.Current.Response.AddHeader("content-disposition", attachment);
    HttpContext.Current.Response.ContentType = "application/csv";
    HttpContext.Current.Response.AddHeader("Pragma", "public");
    HttpContext.Current.Response.Write(contentToExport);
    System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest();
}


您是否尝试过
bcp
实用程序<代码>应用程序中断并停止响应,我无法通过web浏览器下载。请更明确地说明这意味着什么。它是如何工作的?你不回应是什么意思?为什么你不能下载(它是否显示错误?超时(如果是,那么这么长时间后)?其他东西?@RogerWolf:我需要在从应用程序发出请求时生成实时文件。不知道我是否可以用bcp处理它,因为传递给SP的参数可以根据用户的不同而变化requirement@mjwills:早些时候,我有一个直接的代码,可以从数据库中获取数据作为数据表,并开始写入.csv文件,该文件的数据大小很小,比如说30到50MB。现在,随着数据大小和生成的文件增长到350到400 MB,应用程序停止响应或者说请求在中间被杀死。甚至有时Web浏览器也会停止responding@mjwills基本上,当数据仍在从sql server获取时,它们的应用程序端看起来是一个超时。我尝试在DAL层中将方法的超时设置为0。还是一样。您是否尝试过
bcp
实用程序<代码>应用程序中断并停止响应,我无法通过web浏览器下载。请更明确地说明这意味着什么。它是如何工作的?你不回应是什么意思?为什么你不能下载(它是否显示错误?超时(如果是,那么这么长时间后)?其他东西?@RogerWolf:我需要在从应用程序发出请求时生成实时文件。不知道我是否可以用bcp处理它,因为传递给SP的参数可以根据用户的不同而变化requirement@mjwills:早些时候,我有一个直接的代码,可以从数据库中获取数据作为数据表,并开始写入.csv文件,该文件的数据大小很小,比如说30到50MB。现在,随着数据大小和生成的文件增长到350到400 MB,应用程序停止响应或者说请求在中间被杀死。甚至有时Web浏览器也会停止responding@mjwills基本上,当数据仍在从sql server获取时,它们的应用程序端看起来是一个超时。我尝试在DAL层中将方法的超时设置为0。还是一样。这是有道理的,因为它不使用我的服务器内存,而是继续直接写入文件。不过,当我不得不下载文件大小为350MB的数据时,感觉有点慢。我们有什么方法可以让工作更快吗。@ParthKalra首先,添加一个
秒表
,并收集查询执行的持续时间,读取DataReader中的所有行(不构建csv,只需读取并调用ToString(),最后测量整个持续时间。然后你可以找到这个过程中最慢的部分procedure@openwix:我尝试在执行实际获取数据的SP的开始和结束期间添加注释。获取数据几乎需要5到6分钟。因为我通过隧道网络。如果我在t上以查询模式运行它,它在一分钟内就像一个符咒服务器本身。但在运行应用程序时,需要5-6分钟,因为它通过vpn连接。@openwix:我对您的代码进行了一些调整,因为随着数据大小的不断增加,我无法继续追加数据,因此在while循环中创建了一个字符串生成器,并将其写入文件,以避免内存消耗。它这很有意义,因为它不使用我的服务器内存,一直直接写入文件。不过,当我不得不下载文件大小为350 mb的数据时,感觉有点慢。我们有没有办法使工作更快。@ParthKalra首先,添加一个
秒表
,并收集查询执行的持续时间,读取DataRea中的所有行der(不构建csv,只需读取并调用ToString(),最后测量整个持续时间。然后你可以找到这个过程中最慢的部分procedure@openwix:我尝试在执行实际获取数据的SP的开始和结束期间添加注释。获取数据几乎需要5到6分钟。因为我通过隧道网络。如果我在t上以查询模式运行它,它在一分钟内就像一个符咒服务器本身。但在运行应用程序时需要5-6分钟,因为它是通过vpn连接的。@openwix:我对您的代码做了一些调整,因为随着数据大小的增加,我无法继续追加数据,因此在while循环中创建了一个字符串生成器,并将其写入文件,以避免内存消耗。如根据我的代码,我也是c