【问题标题】:Other way to optimize this C# Code?优化此 C# 代码的其他方法?
【发布时间】:2012-05-23 13:36:16
【问题描述】:

我创建了 mdb 记录到 sql 记录的转换,对我来说它工作正常.. 但是当记录很大时速度很慢..我认为还有其他方法可以优化记录的解析和提取??

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Data;
using System.Data.OleDb;    

namespace conMDBToSQL
{
    class Program
    {
        static void Main()
        {

            // string sFileName = "C:\\sqlrecords.mdb";
            string sFileName = "C:\\sample.mdb";
            OleDbConnection _con = new OleDbConnection( @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + sFileName + ";Mode=Share Exclusive;User Id=admin;Password=;" );
            try
            {
                _con.Open();

                string sTableName = "users";

                string strSQL = String.Empty;

                strSQL = "SELECT * FROM " + sTableName + " ORDER BY 1";
                OleDbCommand _cmd = new OleDbCommand( strSQL, _con );
                _cmd.CommandType = CommandType.Text;
                OleDbDataReader _dr = _cmd.ExecuteReader( CommandBehavior.SchemaOnly );

                ArrayList _Arr = new ArrayList();


                DataTable dt = _dr.GetSchemaTable();
                foreach ( DataRow drow in dt.Rows )
                {
                    // Console.Write( drow[0].ToString() + "\n" );
                    _Arr.Add( drow[0].ToString() );
                }
                _dr.Close();
                _cmd.Dispose();


                strSQL = "SELECT * FROM " + sTableName + " ORDER BY 1";
                _cmd = new OleDbCommand(strSQL, _con);
                _cmd.CommandType = CommandType.Text;
                _dr = _cmd.ExecuteReader();

                string s_fields = String.Empty;
                string s_values = String.Empty;
                int arr_count = _Arr.Count - 1;
                while (_dr.Read()) 
                {
                    for(int i_a = 0; i_a <= arr_count;i_a++)
                    {
                        if (i_a <= arr_count)
                        {
                            s_fields += _Arr[i_a].ToString() + ",";
                            s_values += "'" + _dr[i_a].ToString() + "',";
                        }
                        else
                        {
                            s_fields += _Arr[i_a].ToString();
                            s_values += "'" + _dr[i_a].ToString() + "'";
                        }
                    }

                    // Build, query
                    strSQL = String.Empty;
                    strSQL = "INSERT INTO " + sTableName + "("+ s_fields +") VALUES ("+ s_values +")";

                    // Write, text file
                    StreamWriter sw = new StreamWriter(sFileName, true, Encoding.UTF8);
                    sw.Write(strSQL);
                    sw.Close();
                    sw = null;
                }


                Console.WriteLine("\n");
                Console.WriteLine("Finished..");
                Console.ReadKey();
            }
            catch ( OleDbException olex )
            {
                throw olex;
            }
            finally 
            {
                _con.Close();
            }

        }
    }
}

谢谢,

【问题讨论】:

  • 可能更适合codereview.stackexchange.com
  • 似乎完成这项任务的最佳方法实际上是根本不编写任何代码。访问中内置了一些工具,无需自定义代码解决方案即可将此数据导入 SQL 服务器:stackoverflow.com/questions/370619/…
  • Nikhil,你的场景是什么?如果我们知道您的要求,我们或许可以提出更强大、更快速的建议。
  • 使用 for 而不是 foreach 并且不要使用 ToString() (_Arr.Add( drow[0].ToString() );) 在使用 ArrayList 时,您可以将对象放在那里。是的,使用 StringBuilder 效率更高。
  • 我不明白这个条件 if (i_a

标签: c# optimization streaming file-conversion


【解决方案1】:

SqlBulkCopy 类帮助了我一次。 Link here

【讨论】:

    【解决方案2】:

    我看到两个主要问题。首先,您应该在循环的开头打开StreamReader,并在完成后将其关闭。像这样:

    using (StreamWriter sw = new StreamWriter(sFilename, false, Encoding.UTF8)
    {
        while (dr.Read())
        {
            // convert here
            // Each line is written to the StreamWriter
        }
    }
    

    using 构造将确保 StreamWriter 正确关闭和处置。

    第二个问题是将内容附加到字符串。不要附加字符串,而是使用StringBuilder:

    StringBuilder s_fields = new StringBuilder();
    StringBuilder s_values = new StringBuilder();
    int arr_count = _Arr.Count - 1;
    while (_dr.Read()) 
    {
        for(int i_a = 0; i_a <= arr_count;i_a++)
        {
            if (i_a <= arr_count)
            {
                s_fields.AppendFormat("{0},", _Arr[i_a].ToString());
                s_values.AppendFormat("'{0}',", _dr[i_a].ToString());
            }
            else
            {
                s_fields.Append(_Arr[i_a].ToString());
                s_values.AppendFormat("'{0}'", _dr[i_a].ToString());
            }
        }
        strSQL = String.Format("INSERT INTO {0} ({1}) VALUES ({2})",
            sTableName, s_fields.ToString(), s_values.ToString());
        sw.WriteLine(strSQL);
    }
    

    这应该会大大提高你的表现。

    【讨论】:

      【解决方案3】:

      我认为你的主要罪魁祸首是new StreamWriter(sFileName, true, Encoding.UTF8) 代码行。对于每个数据行,您正在打开文件、添加单个命令,然后关闭文件。那将是非常低效的。

      尝试使用StringBuilder 而不是写入流,然后在读取循环之外,将使用StringBuilder 构建的字符串写入文件一次。

      我想你会发现这大大加快了速度。

      【讨论】:

      • 只要他写的数据总量不超过 10 亿个字符,就可以了。
      • @JimMischel - 然后他可以进行部分写入,但我怀疑如果这是他达到的限制,那么他可能会遇到更多问题。这将是一张非常大的桌子。
      • 几千兆字节对我来说听起来不是一张很大的桌子。
      猜你喜欢
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      • 2011-11-24
      • 2020-09-02
      • 2022-07-11
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多