快速有效地从数据库将大量数据写入CSV文件的方法

时间:2018-06-21 12:27:00

标签: c# sql database csv

我正在创建一个程序,该程序将从DB中获取数据并使用CSV文件将其写入磁盘,主要问题是DB可以具有6列以上和3000行以上。

我正在使用CSV Helper来从字符串数组写入CSV文件。 我知道这不是最好的方法,因此您可以给我一些有关快速有效方法的想法的想法, CSV文件没有等待 +20分钟吗?

这是我编写的将数据写入CSV文件的代码(我觉得这不是实现此目的的好方法

// Start writing the CSV file
using (TextWriter _w  = new StreamWriter(String.Format("{0}{1}[{2}].csv", args[2], args[1], GetDateTime())))
using (CsvWriter  _csv = new CsvWriter(_w)) {
    _csv.Configuration.Delimiter = ",";

    // Writes the column names
    for (int i = 0; i < ODBCSQL.ColumnsCount; i++)
        _csv.WriteField(ODBCSQL.GetColumnName(i));

    // Starts writing the rows
    _csv.NextRecord();

    int _columnID = 0;
    int _cnt      = 0;

    while (_cnt < ODBCSQL.ElementsCount) {
        string[] _elements = ODBCSQL.GetElements(_columnID);

        _csv.WriteField(_elements[_cnt], true);

        if (_columnID == ODBCSQL.ColumnsCount - 1)
            _csv.NextRecord();

        if (_columnID != ODBCSQL.ColumnsCount - 1) {
            _columnID++;
        } else {
            _columnID = 0;
            _cnt++;
        }
    }

    MessageBox.Show("CSV Phase 1 : ok");

    _w.Flush();

    MessageBox.Show("CSV Phase 2 : ok");
}

P.S:ODBCSQL类只是我编写的一个辅助类。

下面是ODBCSQL帮助程序类的代码

#region [ODBC_SQL_HELPER_CLASS]
    public static class ODBCSQL {
        private static OdbcConnection _connection;
        private static OdbcDataReader _reader;
        private static string         _cmd;

        public static int             ColumnsCount  = 0;
        public static int             ElementsCount = 0;

        #region [CONNECTION]
        public static bool Connect(string ConnectionString, string Command) {
            _connection = new OdbcConnection(ConnectionString);
            _cmd        = Command;

            try {
                _connection.Open();

                // Test to see if we can read data from the DB
                if (!ReadData())
                    return false;

                return true;
            } catch {
                CloseConnection();

                return false;
            }
        }

        // Dispose
        public static void CloseConnection() {
            try { _connection.Close(); } catch { }
        }
        #endregion

        #region [DATA]
        private static void ResetReader() {
            _reader.Close();
            _reader = (new OdbcCommand(_cmd, _connection)).ExecuteReader();
        }

        private static bool ReadData() {
            try {
                _reader = (new OdbcCommand(_cmd, _connection)).ExecuteReader();

                // Retrieve the number of columns
                ColumnsCount  = _reader.FieldCount;
                ElementsCount = GetElementsCount();

                return true;
            } catch {
                return false;
            }
        }
        private static int GetElementsCount() {
            int _cnt = 0;

            ResetReader();

            while (_reader.Read())
                _cnt++;

            return _cnt;
        }
        public static string GetColumnName(int ColumnID) {
            return _reader.GetName(ColumnID);
        }
        public static string[] GetElements(int ColumnID) {
            List<string> _elements = new List<string>();
            ResetReader();

            while (_reader.Read())
                _elements.Add(_reader[ColumnID].ToString());

            return _elements.ToArray();
        }
        #endregion
    }
    #endregion

也许是ResetReader()了吗?

2 个答案:

答案 0 :(得分:1)

我知道这不是ac#答案,但是我建议您使用专门设计用来执行此任务的ETL工具进行此类工作(大量数据导出/导入),尤其是在这种类型的请求不是一个的情况下,休假类型的东西。一些示例ETL工具是:

  1. SQL Server集成服务
  2. Pentaho数据集成

答案 1 :(得分:0)

我解决了。

问题是public static List<string> GetAllElements() { List<string> _elements = new List<string>(); ResetReader(); while (_reader.Read()) { for (int i = 0; i < ColumnsCount; i++) _elements.Add(_reader[i].ToString()); } return _elements; } 函数,我每次在CSV 编写循环中都调用它,这一次又一次地迭代所有“元素” (数据)。

解决方案:

// Start writing the CSV file
using (TextWriter _w   = new StreamWriter(String.Format("{0}\\{1}[{2}].csv", args[2], args[1], GetDateTime())))
using (CsvWriter  _csv = new CsvWriter(_w)) {
    _csv.Configuration.Delimiter = ",";

    // Writes the column names
    for (int i = 0; i < ODBCSQL.ColumnsCount; i++)
        _csv.WriteField(ODBCSQL.GetColumnName(i));
    _csv.NextRecord();

    // Starts writing the rows
    List<string> _elements = ODBCSQL.GetAllElements();
    for (int i = 0; i < (ODBCSQL.ElementsCount * ODBCSQL.ColumnsCount); i += ODBCSQL.ColumnsCount) {
        for (int j = 0; j < ODBCSQL.ColumnsCount; j++) {
            _csv.WriteField(_elements[i + j], true);

            if (j == ODBCSQL.ColumnsCount - 1)
                _csv.NextRecord();
        }
    }
    _w.Flush();
}

我用它仅从选定列中检索一次数据库中的所有元素。

然后写入文件

{{1}}

感谢大家的帮助!