1

有一个带有上传按钮的网络表单来上传 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

4 回答 4

1

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

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

于 2012-11-01T02:01:29.943 回答
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 表创建 Column Mappings,使用 BulkCopy 对象插入您的数据。参考 BulkCopy:http: //msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

于 2012-10-31T23:50:30.050 回答
0

不是真正的答案,但作为评论发布太长了......

看起来您正在丢弃解析的值(memnbr等...),您可以将 csv 解析代码显着减少为:

return 
 File
   .ReadLines(filename)
   .Skip(1)
   .Select(line => line.Split(','))
   .ToList();
于 2012-10-31T23:54:45.617 回答
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();
于 2012-11-01T11:08:15.643 回答