65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET WebForms:将 CSV 文件上传并导入到 SQL Server

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.70/5 (7投票s)

2016 年 8 月 18 日

CPOL

4分钟阅读

viewsIcon

48733

downloadIcon

5087

一个快速演示,展示如何在 ASP.NET WebForms 中将 CSV 文件上传并导入到 SQL Server 数据库。

引言

多年前,我曾参与一个涉及将 CSV 文件上传并导入到 SQL Server 数据库的小型内部项目,因此我想写一篇文章来演示我为该项目实现的简单方法,供其他可能需要此功能的人参考。

正如一些人可能已经知道的那样,将 CSV 文件导入 SQL Server 很容易,但当 CSV 文件包含许多具有各种数据类型的列时,就会出现困难。基本上,提供程序无法区分列或行的er类型,因此它会盲目地根据前几行将它们视为某种数据类型,并忽略所有不符合该数据类型的数据。为了克服这个问题,我们将使用 `schema.ini` 文件来定义 CSV 文件中存储的数据类型,并允许提供程序读取该文件并识别每列的确切数据类型。

使用代码

Schema.ini

摘自此 帖子:`Schema.ini` 是一个信息文件,用于定义 CSV 文件中包含数据的每一列的数据结构和格式。如果目录中存在 `schema.ini` 文件,Microsoft.Jet.OLEDB 提供程序会自动读取它并识别 CSV 文件中每一列的数据类型信息。因此,在将数据插入数据库之前,提供程序会智能地避免数据类型被错误解释。有关更多信息,请参阅:Schema.ini 文件 (文本文件驱动程序)

创建 schema.ini 之前的注意事项

  1. 模式信息文件必须始终命名为“schema.ini”。
  2. schema.ini 文件必须与 CSV 文件所在的目录相同。
  3. 必须在读取 CSV 文件之前创建 schema.ini 文件。
  4. schema.ini 的第一行必须是 CSV 文件名,后跟 CSV 文件的属性,然后是 CSV 文件中每一列的属性。

以下是 schema 应该是什么样子的示例

[Employee.csv] 
ColNameHeader = False 
Format = CSVDelimited 
DateTimeFormat = dd-MMM-yyyy 
Col1 = EmployeeID Long 
Col2 = EmployeeFirstName Text Width 100 
Col3 = EmployeeLastName Text Width 50 
Col4 = EmployeeEmailAddress Text Width 50

为了简单起见,我们将为此演示使用上述 schema。现在,让我们创建一个简单的空白数据库。您可以随意命名您的数据库,但仅为演示目的,我创建了一个名为 DemoDB 的数据库。

创建数据库后,启动 Visual Studio,然后创建一个新的 WebForms Web 应用程序项目。

在根应用程序下创建一个名为“UploadedCSVFiles”的文件夹,然后将 schema.ini 放在该文件夹中。上传的 CSV 文件在用户导入文件后也将存储在此文件夹中。

ASPX 标记

现在向项目中添加一个新的 WebForm 页面。使用以下服务器控件创建 HTML 标记。

  • 1 FileUpload
  • 1 Button
  • 3 Labels

HTML 标记应该看起来像这样

<%@ Page Language="C#" AutoEventWireup="true" 
         CodeBehind="CSVToSQL.aspx.cs" 
         Inherits="CSVToSQL.CSVToSQL" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Importing CSV to SQL Server Demo</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:FileUpload ID="FileUpload1" runat="server" />  
        <asp:Button ID="btnImport" runat="server" Text="Import" OnClick="btnImport_Click"/>  
        <br />  
        <asp:Label ID="Label1" runat="server" ForeColor="Blue" />  
        <br />  
        <asp:Label ID="Label2" runat="server" ForeColor="Green" />  
        <br />  
        <asp:Label ID="lblError" runat="server" ForeColor="Red" /> 
    </div>
    </form>
</body>
</html>

Web.Config

接下来,我们需要定义连接字符串以便与我们的数据库进行通信。以下是在 web.config 文件中 <configuration> 节点内定义的连接字符串配置示例

  <connectionStrings>
    <add name="DBConnection" 
         connectionString="Data Source=(localdb)\MSSQLLocalDB;
                          Initial Catalog=DemoDB;
                          Integrated Security=True;
                          Connect Timeout=30;
                          Encrypt=False;
                          TrustServerCertificate=True;
                          ApplicationIntent=ReadWrite;
                          MultiSubnetFailover=False"
         providerName="System.Data.SqlClient"/>
  </connectionStrings>

后台代码

之后,我们现在可以继续进行上传 CSV 文件并将其导入 SQL Server 数据库的代码。以下是完整代码。

using System;
using System.Configuration;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.IO;

namespace CSVToSQL
{
    public partial class CSVToSQL : System.Web.UI.Page
    {
        private string GetConnectionString(){
            return ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString;
        }

        private void CreateDatabaseTable(DataTable dt, string tableName){
            string sqlQuery = string.Empty;
            string sqlDBType = string.Empty;
            string dataType = string.Empty;
          
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(string.Format("CREATE TABLE {0} (", tableName));

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                int maxLength = 0;
                dataType = dt.Columns[i].DataType.ToString();
                if (dataType == "System.Int32"){
                    sqlDBType = "INT";
                }
                else if (dataType == "System.String"){
                    sqlDBType = "NVARCHAR";
                    maxLength = dt.Columns[i].MaxLength;
                }
                else{
                    //do something else
                }

                if (maxLength > 0)
                    sb.AppendFormat(string.Format("{0} {1} ({2}), ", dt.Columns[i].ColumnName, sqlDBType, maxLength));
                else
                    sb.AppendFormat(string.Format("{0} {1},", dt.Columns[i].ColumnName, sqlDBType));
            }

            sqlQuery = sb.ToString();
            sqlQuery = sqlQuery.Trim().TrimEnd(',');
            sqlQuery = sqlQuery + " )";

            using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
            {
                sqlConn.Open();
                using (SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn))
                {
                    sqlCmd.ExecuteNonQuery();
                    sqlConn.Close();
                }
            }
        }

        private void LoadDataToDatabase(string tableName, string fileFullPath, string delimeter)
        {
            string sqlQuery = string.Empty;
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(string.Format("BULK INSERT {0} ", tableName));
            sb.AppendFormat(string.Format(" FROM '{0}'", fileFullPath));
            sb.AppendFormat(string.Format(" WITH ( FIELDTERMINATOR = '{0}' , ROWTERMINATOR = '\n' )", delimeter));
            sqlQuery = sb.ToString();

            using (SqlConnection sqlConn = new SqlConnection(GetConnectionString()))
            {
                sqlConn.Open();
                using (SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn))
                {
                    sqlCmd.ExecuteNonQuery();
                    sqlConn.Close();
                }
            }
        }

        private void UploadAndProcessFile()
        {
            if (FileUpload1.HasFile)
            {
                FileInfo fileInfo = new FileInfo(FileUpload1.PostedFile.FileName);
                if (fileInfo.Name.Contains(".csv"))
                {
                    string fileName = fileInfo.Name.Replace(".csv", "").ToString();
                    string csvFilePath = Server.MapPath("UploadedCSVFiles") + "\\" + fileInfo.Name;

                    //Save the CSV file in the Server inside 'UploadedCSVFiles'   
                    FileUpload1.SaveAs(csvFilePath);

                    //Fetch the location of CSV file   
                    string filePath = Server.MapPath("UploadedCSVFiles") + "\\";

                    string strSql = string.Format("SELECT * FROM [{0}]", fileInfo.Name);
                    string strCSVConnString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='text;HDR=YES;'", filePath);

                    // load the data from CSV to DataTable   
                    DataTable dtCSV = new DataTable();
                    DataTable dtSchema = new DataTable();
                    using (OleDbDataAdapter adapter = new OleDbDataAdapter(strSql, strCSVConnString))
                    {
                        adapter.FillSchema(dtCSV, SchemaType.Mapped);
                        adapter.Fill(dtCSV);
                    }

                    if (dtCSV.Rows.Count > 0)
                    {
                        CreateDatabaseTable(dtCSV, fileName);
                        Label2.Text = string.Format("The table ({0}) has been successfully created to the database.", fileName);
                        string fileFullPath = filePath + fileInfo.Name;
                        LoadDataToDatabase(fileName, fileFullPath, ",");
                        Label1.Text = string.Format("({0}) records has been loaded to the table {1}.", dtCSV.Rows.Count, fileName);
                    }
                    else
                    {
                        lblError.Text = "File is empty.";
                    }
                }
                else
                {
                    lblError.Text = "Unable to recognize file.";
                }
            }
        }

        protected void btnImport_Click(object sender, EventArgs e)
        {
            UploadAndProcessFile();
        }
    }
}

上面的代码包含以下四个 (4) 个私有方法

GetConnectionString() 是一个返回字符串的方法。此方法基本上从 web.config 文件中获取我们已配置的连接字符串。

CreateDatabaseTable() 是一个接受两个 (2) 个参数的方法:一个包含数据的 DataTable 和文件名。此方法根据提供的参数自动创建数据库表。

LoadDataToDatabase() 是一个接受三个 (3) 个参数的方法:表名、文件完整路径和分隔符值。此方法是将数据从 CSV 实际导入到 SQL Server 数据库表中的地方。

UploadAndProcessFile() 处理将 CSV 文件上传到指定位置。这也是调用 CreateDatabaseTable() 和 LoadDataToDatabase() 的地方。如果您注意到,我们还在该方法中添加了一些基本的陷阱和验证。

现在让我们创建一些简单的 CSV 格式数据来测试导入实用程序。让我们创建一个名为“Employee.csv”的 CSV 文件,然后添加以下数据(注意格式)

1,Vincent Maverick,Durano,email1@email.com
2,Vianne Maverich,Durano,email2@email.com
3,Vynn Markus,Durano,email3@email.com
4,Michelle,Lorenzana,email4@email.com
5,Xhaiden,Durano,email5@email.com
6,Angel Christine,Durano,email6@email.com
7,Kurt,Durano,email7@email.com
8,Lilibeth,Durano,email8@email.com
9,Warrior,Martinez,email9@email.com
10,Rhamz,Lao,email10@email.com

现在将新创建的 CSV 文件保存在硬盘驱动器的某个位置。

输出

运行页面将得到类似这样的结果

浏览 CSV 文件后

导入后

现在,如果我们查看之前创建的数据库,您会发现 Employee 表已成功创建,并包含导入的数据,如下图所示:

摘要

在本文中,我们学习了如何创建一个简单的 Web 实用程序,该程序允许我们将 CSV 文件上传并导入到 SQL Server 数据库。

© . All rights reserved.