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






4.70/5 (7投票s)
一个快速演示,展示如何在 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 之前的注意事项
- 模式信息文件必须始终命名为“schema.ini”。
- schema.ini 文件必须与 CSV 文件所在的目录相同。
- 必须在读取 CSV 文件之前创建 schema.ini 文件。
- 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 数据库。