上传csv文件,解析,然后将数据插入SQL表

时间:2012-10-31 23:23:11

标签: c# list parsing webforms

有一个webform,它有一个上传按钮来上传csv文件,然后我的代码需要解析文件并使用解析后的数据插入到SQL表中。我正在为分析数据解析数据是正确的,它没有获取流读取器的文件名。这是解析数据最有效的方法吗?我应该解析成数据表吗?

protected void UploadBtn_Click(object sender, EventArgs e)
{
    if (FileUpload.HasFile)
    {

        string filename = Path.GetFileName(FileUpload.FileName);
        List<string[]> ValuesToUpload = parseData(filename);

        //if (!Directory.Exists(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim()))
        //{
        //    Directory.CreateDirectory(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim());
        //}
        //FileUpload.SaveAs(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim() + filename);
        //using (FileStream stream = new FileStream(ConfigurationManager.AppSettings["temp_dir"].ToString().Trim() + filename, FileMode.Open, FileAccess.Read, FileShare.Read))
    }
}
      public List<string[]> parseData(filename)
            {
             int j=0;
             List <string[]> members = new List<string[]>();
             try
             {
                using (StreamReader read = new StreamReader(filename))
                {
                    while (!read.EndOfStream)
                    {
                        string line = read.ReadLine();
                        string[] values = line.Split(',');
                        if(j==0)
                        {
                            j++;
                            continue;
                        }

                        long memnbr = Convert.ToInt64(values[0]);
                        int loannbr = Convert.ToInt32(values[1]);
                        int propval = Convert.ToInt32(values[2]);
                        members.Add(values);
                    }

4 个答案:

答案 0 :(得分:1)

使用KBCsv。我们每秒解析40K行,每秒跳过70K +行。这是我见过的最快的。而且还很稳定。然后按照上面的建议手动生成SQL。如果执行数据重新加载并以性能为目标,则运行多线程,无事务(仅限MS SQL)。每秒最多可以获得10K行的导入速度,具体取决于您对数据库服务器的网络带宽。

不要解析为DataTable - 它非常慢。

答案 1 :(得分:0)

由于您要将数据插入SQL表,我首先创建一个表示表的类,并为每个记录创建一个新对象。 (这是为了能见度)。

或者我可以使用以下方法(假设您正在使用MS SQL Server) 1.动态插入查询

StringBuilder strInsertValues = new StringBuilder("VALUES");

your ParsingCode HERE..
string [] values = line.Split(',');
strInsertValues.AppendFormat("({0},{1},{2}),", values[0], values[1], values[2]);

end parse


using(SqlConnection cn = new SqlConnection(YOUR_CONNECTION_STRING)){
    SqlCommand cmd = cn.CreateCommand;
    cmd.CommandType = SqlCommandType.Text;
    cmd.CommandText = "INSERT INTO TABLE(Column1, Column2, Column3) " + strInsertValues.ToString().SubString(0, strInsertValues.Length);
    cn.Open();
    cmd.ExecuteNonQuery();

}

2。使用BulkCopy(推荐) 创建一个表示CSV值的DataSet 为每个解析的行添加新记录 为DataSet和SQL表创建列映射, 使用BulkCopy对象插入数据。 参考BulkCopy:http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

答案 2 :(得分:0)

不是一个真正的答案,但发表评论的时间太长......

因为看起来你丢弃了解析后的值(memnbr等...),你可以大大减少你的csv解析代码:

return 
 File
   .ReadLines(filename)
   .Skip(1)
   .Select(line => line.Split(','))
   .ToList();

答案 3 :(得分:0)

以下代码示例将批量插入CSV数据到具有匹配列的登台表中,然后执行存储过程以规范化服务器上​​的数据。

这比手动解析数据和逐行插入数据要有效得多。几个月前,我使用类似的代码向我们的数据库提交1,500,000多条记录,并在几秒钟内对数据进行标准化。

var sqlConnection = new SqlConnection(DbConnectionStringInternal);

// Bulk-import our unnormalized data from the .csv file into a staging table
var inputFileConnectionString = String.Format("Driver={{Microsoft Text Driver (*.txt; *.csv)}};Extensions=csv;Readonly=True;Dbq={0}", Path.GetDirectoryName(csvFilePath));
using (var inputFileConnection = new OdbcConnection(inputFileConnectionString))
{
    inputFileConnection.Open();

    var selectCommandText = String.Format("SELECT * FROM {0}", Path.GetFileName(csvFilePath));
    var selectCommand = new OdbcCommand(selectCommandText, inputFileConnection);
    var inputDataReader = selectCommand.ExecuteReader(CommandBehavior.CloseConnection);

    var sqlBulkCopy = new SqlBulkCopy(sqlConnection) { DestinationTableName = "Data_Staging" };    
    if (sqlConnection.State != ConnectionState.Open)
        sqlConnection.Open();

    sqlBulkCopy.WriteToServer(inputDataReader);    
}

// Run a stored-procedure to normalize the data in the staging table, then efficiently move it across to the "real" tables.
var addDataFromStagingTable = String.Format("EXEC SP_AddDataFromStagingTable");
if (sqlConnection.State != ConnectionState.Open)
    sqlConnection.Open();

using (var addToStagingTableCommand = new SqlCommand(addDataFromStagingTable, sqlConnection) { CommandTimeout = 60 * 20 })
    addToStagingTableCommand.ExecuteNonQuery();    

sqlConnection.Close();