【问题标题】:Batch Exporting to CSV批量导出为 CSV
【发布时间】:2016-11-08 04:01:37
【问题描述】:

我正在处理大量约会到 csv 向用户发送通知等。我想要做的是设置一个 isProcessed 标志来表示当前行已经被处理我不知道该怎么做我当前的循环。

public void DumpTableToFile(SqlConnection connection, string tableName, string destinationFile)
    {
        using (var command = new SqlCommand("select LineType,CustomerFirstName AS 'Forename' ,CustomerLastName,Age,dob as 'Date of Birth',maritalStatus AS 'Marital Status',homePhone AS 'Home', mobileNumber AS Mobile,emailAddress AS Email,Address1 + Address2  + PostCode AS 'Address' ,employmentStatus AS Employment,occupation AS Occupation,propertyValue AS 'Property Value',mortgageBalance AS 'Mortgage Balance',balanceOnSecuredDebt AS 'Balance on secured Debt',mortgageType as 'Mortgage Type' from " + tableName, connection))
        using (var reader = command.ExecuteReader())
        using (var outFile = File.CreateText(destinationFile))
        {
            string[] columnNames = GetColumnNames(reader).ToArray();
            int numFields = columnNames.Length;
            outFile.WriteLine(string.Join(",", columnNames));
            if (reader.HasRows)
            {
                while (reader.Read())
                {
                    string[] columnValues =
                        Enumerable.Range(0, numFields)
                                  .Select(i => reader.GetValue(i).ToString())
                                  .Select(field => string.Concat("\"", field.Replace("\"", "\"\""), "\""))
                                  .ToArray();

                    outFile.WriteLine(string.Join(",", columnValues));
                }
            }
        }

该标志称为 isProcessed,一旦通过 csv 导出,我想将其设置为 true。这样我就可以进行批量导出。它存在于同一个表约会中

编辑 1

很抱歉没有说明我希望将此标志写回到约会表中,以便在 csv 导出中吐出当前记录第二次处理。

【问题讨论】:

  • 你想让这个标志做什么?它应该是您写出的文件的一部分吗?内存状态?
  • @EricJ。在那里进行了编辑以解释自己,请参阅编辑 1
  • 非常感谢您的投票,感谢

标签: c# sql-server csv ado.net


【解决方案1】:

执行以下步骤:

  1. 为您的查询添加一个标准:WHERE NOT isProcessed,因此接下来您进行导出,只会处理未处理的记录。
  2. 完成导出后,将此命令发送到数据库:"UPDATE " + tableName + " SET isProcessed=true WHERE <exact same criteria as the select statement>"。这样,所有记录现在都被标记为已处理。
  3. 将 TransactionScope 包装在 export-mechanisme 周围,包括。更新。这样,当某些事情发生故障时,整个操作将被回滚。
  4. TransactionScope 周围加上一个try-catch,这样当导出失败时,CSV 文件将被删除,因此您永远不会有一半导出的批次。

你的代码会变成这样(我没有测试过):

public void DumpTableToFile(SqlConnection connection, string tableName, string destinationFile)
{
    try
    {
        using(var transaction = new TransactionScope())
        {
            // Select all non-processed records.
            using (var command = new SqlCommand("select LineType,CustomerFirstName AS 'Forename' ,CustomerLastName,Age,dob as 'Date of Birth',maritalStatus AS 'Marital Status',homePhone AS 'Home', mobileNumber AS Mobile,emailAddress AS Email,Address1 + Address2  + PostCode AS 'Address' ,employmentStatus AS Employment,occupation AS Occupation,propertyValue AS 'Property Value',mortgageBalance AS 'Mortgage Balance',balanceOnSecuredDebt AS 'Balance on secured Debt',mortgageType as 'Mortgage Type' from " + tableName 
                + " WHERE NOT isProcessed", connection))
            using(var reader = command.ExecuteReader())
            using(var outFile = File.CreateText(destinationFile))
            {
                string[] columnNames = GetColumnNames(reader).ToArray();
                int numFields = columnNames.Length;
                outFile.WriteLine(string.Join(",", columnNames));
                if (reader.HasRows)
                {
                    while(reader.Read())
                    {
                        string[] columnValues =
                            Enumerable.Range(0, numFields)
                                .Select(i => reader.GetValue(i).ToString())
                                .Select(field => string.Concat("\"", field.Replace("\"", "\"\""), "\""))
                                .ToArray();

                        outFile.WriteLine(string.Join(",", columnValues));
                    }
                }
            }

            // Update the same records that were just exported.
            using (var command = new SqlCommand("UPDATE " + tableName + " SET isProcessed=true WHERE NOT isProcessed", connection))
                command.ExecuteNonQuery();

            transaction.Complete();
        }
    }
    catch
    {
        // If something went wrong, delete the export file.
        File.Delete(destinationFile);
        throw;
    }
}

【讨论】:

  • 嗨,TransactionScope 来自哪里?它根本无法解决我的问题
  • 您已经引用了 System.Transactions.dll。
  • 这是一个很好的答案,但如果用户能够影响 tableName 的内容(就像 OP 的代码一样),则容易受到 SQL 注入攻击。 @david 请确保这是不可能的。在使用用户输入构造查询时,请务必使用参数化查询。
  • @EricJ。这仅在控制台应用程序上运行,因此并不真正适用或确实如此?
  • 控制台应用程序可以直接从用户或从用户控制下的配置文件中获取输入。只需确保恶意用户不可能影响您的变量 tableName 中的内容。
猜你喜欢
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2018-07-15
  • 1970-01-01
  • 2014-12-22
  • 2014-02-03
相关资源
最近更新 更多