使用C#和asp.net将CSV文件导入SQL

时间:2014-08-04 12:28:32

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

我正在使用SQL Server 2014.我的网络应用程序的一个功能是上传CSV文件,并将数据导入我的数据库中的一个表(称为TF)(称为{{ 1}})。

我不知道该怎么做。

TMPA

我尝试了这段代码,但它无法运行。

PS:string excelPath = Server.MapPath("~/Files/") + Path.GetFileName(FileUpload2.PostedFile.FileName); FileUpload1.SaveAs(excelPath); SqlConnection con = new SqlConnection(@"Data Source=SAMSUNG-PC\SQLEXPRESS;Initial Catalog=TMPA;Persist Security Info=True"); StreamReader sr = new StreamReader(excelPath); string line = sr.ReadLine(); string[] value = line.Split(','); DataTable dt = new DataTable(); DataRow row; foreach (string dc in value) { dt.Columns.Add(new DataColumn(dc)); } while (!sr.EndOfStream) { value = sr.ReadLine().Split(','); if (value.Length == dt.Columns.Count) { row = dt.NewRow(); row.ItemArray = value; dt.Rows.Add(row); } } SqlBulkCopy bc = new SqlBulkCopy(con.ConnectionString, SqlBulkCopyOptions.TableLock); bc.DestinationTableName = "TF"; bc.BatchSize = dt.Rows.Count; con.Open(); bc.WriteToServer(dt); bc.Close(); con.Close(); 的列数比CSV文件多:有些列是计算出来的,应该在每次插入后自动计算..

这是我的CSV文件的画布:4列:

TF

IdProduit,Mois,Reel,Budget 是字符串,IdProduit是日期,MoisReel是浮点数。

另一方面,我的SQL Server表如下所示:

Budget

所有其他列应为空或自动计算。

帮助我!

3 个答案:

答案 0 :(得分:1)

你走在正确的道路上。在将数据插入SQL Server时,使用SqlBulkCopy将提供最佳性能。但是,与编写自己的Csv解析器相反,我将通过Microsoft.VisualBasic程序集中的TextFieldParser类使用.NET Framework中提供的恒星解析器。您可能需要进行一些挖掘以查看SqlBulkCopy是否允许使用部分数据集。我不相信它,但您可以将缺少的列添加到DataTable中,然后再将其作为解决方法发送到SqlBulkCopy。

答案 1 :(得分:1)

我使用名为Filehelpers的开源.net库修复了它。 这是链接:http://www.filehelpers.net/

这就是我的所作所为:

 <asp:FileUpload ID="FileUpload1" runat="server" />
        <asp:Button ID="Button1" OnClick = "UploadF" runat="server" Text="Importer" />

这是背后的代码:

    [DelimitedRecord("|")]
    public class TBFtable 
{ 
    public string IdProduit; 
    public DateTime Mois; 
    public float Reel; 
    public float Budget; 

} 

    protected void UploadF(object sender, EventArgs e)

    {

        string excelPath = Server.MapPath("~/Files/") + Path.GetFileName(FileUpload1.PostedFile.FileName);
        FileUpload1.SaveAs(excelPath);

        SqlServerStorage storage = new SqlServerStorage(typeof(TBFtable),ConfigurationManager.ConnectionStrings["bd"].ConnectionString);


         storage.InsertSqlCallback = new InsertSqlHandler(GetInsertSqlCust);

        TBFtable[] res = CommonEngine.ReadFile(typeof(TBFtable), excelPath) as TBFtable[]; 
        storage.InsertRecords(res);
        ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "alertMessage", "alert('Données enregistrées avec succès !')", true);
    }

    protected string GetInsertSqlCust(object record) 
{ 
    TBFtable obj = (TBFtable) record; 

    return String.Format("INSERT INTO TF (IdProduit, Mois, Reel, Budget ) " +  " VALUES ( '{0}' , '{1}' , '{2}' , '{3}'  ); ", obj.IdProduit, obj.Mois,obj.Reel, obj.Budget ); 

} 

答案 2 :(得分:0)

我知道这是一个古老的问题,但是对于任何可能感兴趣的人。

除非您确定文件永远不会很大,否则应避免像DataTable方法和(我认为)您接受的答案一样,将整个批处理加载到内存中并立即将其全部发送到SQL Server。 。您可能会冒着在客户端(在这种情况下,您的文件处理服务器)的内存不足异常的风险,或者更糟的是,在SQL Server方面。通过使用SqlBulkCopy类和IDataReader接口的实现,可以避免这种情况。

我写了一个程序包,我认为在您这样的情况下可能会引起您的兴趣。代码如下所示:

var dataReader = new CsvDataReader("pathToYourCsv",
            new List<TypeCode>(4)
            {
                TypeCode.String, //IdProduit
                TypeCode.DateTime, //Mois
                TypeCode.Double, //Reel
                TypeCode.Double //Budget
            });

        this.bulkCopyUtility.BulkCopy("tableName", dataReader);

对于更复杂的情况(灵活的列映射,csv文件中不存在的其他静态列值,值转换),还有其他配置选项。 package是开放源代码(project on Github),应该可以在.NET Core和.NET Framework上使用。

作为补充,进行大量SQL导入时,SQL Server恢复模式可能很重要。尽可能使用“简单日志记录”或“大容量日志记录”以避免大量事务文件。