You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# .NET导出CSV函数泛化优化及重复查询问题求助

C# Oracle数据导出CSV代码优化

原代码存在以下问题:

  • 同一Company_ID会被多次遍历并重复执行数据库查询
  • 硬编码指定Company_ID的值(如10、1000)
  • 首次查询仅用于遍历数据,属于冗余操作

优化要点

  1. 避免重复查询:先获取唯一的Company_ID列表,对每个ID只执行一次导出查询
  2. 移除硬编码:把需要处理的Company_ID改成方法参数传入,或者从配置文件读取,灵活调整目标对象
  3. 删除冗余查询:直接针对目标Company_ID查询导出数据,去掉无意义的初始遍历查询
  4. 安全与资源优化:用参数化查询防止SQL注入,用using语句自动释放连接、流等资源,避免内存泄漏
  5. 代码复用:把重复的逻辑(比如生成文件名、查询数据、CSV值转义)抽成独立方法,让代码更整洁

优化后的完整代码

GetData函数及辅助查询方法

// 可传入需要处理的CompanyID列表,替代硬编码
DataTable GetData(List<int> targetCompanyIds)
{
    string chargeMonth = DateTime.Now.ToString("yyyyMM");
    string creationDate = DateTime.Now.ToString("yyyyMMdd");
    string creationTime = DateTime.Now.ToString("HHmmss");
    string constVal = "MLL";
    string fileType = "HIYUV-CHEVRA";

    var connectString = "Data Source=192.168.117.1;User ID=*;Password=*";
    
    // using自动释放数据库连接资源
    using (OracleConnection con = new OracleConnection(connectString))
    {
        con.Open();
        
        // 对CompanyID去重,避免重复查询
        foreach (int companyId in targetCompanyIds.Distinct())
        {
            // 拼接文件名
            string fileName = $"{constVal}-{fileType}-{companyId}-{chargeMonth}-{creationDate}-{creationTime}.csv";
            
            // 查询当前CompanyID的导出数据
            DataTable exportData = GetExportDataByCompanyId(con, companyId);
            
            // 执行CSV导出
            ExportExcelGeneric(exportData, fileName);
        }

        // 若业务仍需要返回初始查询结果,保留此部分;不需要可直接删除
        using (OracleCommand cmd = con.CreateCommand())
        {
            cmd.CommandText = "Select * from BAKASHOT_PIRTY_MEIDA WHERE PROD IS NULL and CHARGED = 0";
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            return dt;
        }
    }
}

// 提取查询逻辑为独立方法,复用代码
DataTable GetExportDataByCompanyId(OracleConnection connection, int companyId)
{
    using (OracleCommand cmd = connection.CreateCommand())
    {
        // 参数化查询,防止SQL注入
        cmd.CommandText = "Select * from BAKASHOT_PIRTY_MEIDA WHERE COMPANY_ID = :CompanyId and PROD IS NULL and CHARGED = 1";
        cmd.Parameters.Add(":CompanyId", OracleDbType.Int32).Value = companyId;
        
        DataTable dt = new DataTable();
        dt.Load(cmd.ExecuteReader());
        return dt;
    }
}

优化后的CSV导出函数

void ExportExcelGeneric(DataTable dataTable, string filename)
{
    // 用Path.Combine处理路径,避免语法错误
    string filePath = Path.Combine(@"D:\", filename);
    // using自动释放StreamWriter资源
    using (StreamWriter sw = new StreamWriter(filePath, false, Encoding.UTF8))
    {
        // 写入表头
        for (int i = 0; i < dataTable.Columns.Count; i++)
        {
            sw.Write(EscapeCsvValue(dataTable.Columns[i].ColumnName));
            if (i < dataTable.Columns.Count - 1)
            {
                sw.Write(",");
            }
        }
        sw.WriteLine();

        // 写入数据行
        foreach (DataRow dr in dataTable.Rows)
        {
            for (int i = 0; i < dataTable.Columns.Count; i++)
            {
                if (!Convert.IsDBNull(dr[i]))
                {
                    sw.Write(EscapeCsvValue(dr[i].ToString()));
                }
                if (i < dataTable.Columns.Count - 1)
                {
                    sw.Write(",");
                }
            }
            sw.WriteLine();
        }
    }
}

// 提取CSV值转义逻辑,处理逗号、双引号、换行等特殊情况
string EscapeCsvValue(string value)
{
    if (value.Contains(',') || value.Contains('"') || value.Contains('\n') || value.Contains('\r'))
    {
        // 转义双引号,用双引号包裹内容
        return $"\"{value.Replace("\"", "\"\"")}\"";
    }
    return value;
}

额外建议

  • 配置化管理:把数据库连接字符串、目标CompanyID、文件存储路径放到配置文件(如appsettings.json)中,彻底消除硬编码
  • 错误处理:添加try-catch块捕获数据库操作、文件写入的异常,提升程序稳定性
  • 日志记录:记录导出的CompanyID、文件名、成功/失败状态,方便后续排查问题

内容的提问来源于stack exchange,提问作者user20622377

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:15:26