Uploading and Importing CSV File to SQL Server

ASP.NET:  Automatic Database Table Creation

A few years ago I was working with a small internal project that involves uploading and importing CSV files to a SQL Server database and thought I'd write an article that demonstrates my simple implementation for the project here in C# Corner.

As some may already know, importing a CSV file into SQL Server is easy and simple but difficulties arise when the CSV file contains, many columns with various data types. Basically, the provider cannot differentiate the data types of the columns or the rows, so it blindly considers them as a data type based on the first few rows and ignores all the data that does not match the data type. To overcome this problem, I used a schema.ini file to define the data type stored within the CSV file and allow the provider to read that and recognize the exact data types of each column.

schema.ini

Taken from the documentation: The Schema.ini is an information file, used to define the data structure and format of each column that contains data in the CSV file. If schema.ini file exists in the directory, Microsoft.Jet.OLEDB provider automatically reads it and recognizes the data type information of each column in the CSV file. Thus, the provider intelligently avoids the misinterpretation of data types before inserting the data into the database. For more information see: Schema.ini File.

Points to remember before creating schema.ini

  1. The schema information file must always named "schema.ini".
  2. The schema.ini file must be kept in the same directory where the CSV file exists.
  3. The schema.ini file must be created before reading the CSV file.
  4. The first line of the schema.ini, must the name of the CSV file, followed by the properties of the CSV file and then the properties of the each column in the CSV file.

The following is an example of how the schema should look:

  1. [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
To get started, let's go ahead and create a simple blank database. Just for the purpose of this demo I created a database called DemoDB.

After creating the database, go ahead and fire up Visual Studio and then create a new WebApplication project.

Under the root application create a folder and name it “UploadedCSVFiles” and then place the schema.ini on that folder. The uploaded CSV files will be stored in this folder after the user imports the file.

Now add a WebForm page to the project. Create the HTML markup with the following server controls.
  • 1 FileUpload
  • 1 Button
  • 3 Labels

The HTML markup should look something like this:

  1. <asp:FileUpload ID="FileUpload1" runat="server" />  
  2. <asp:Button ID="btnImport" runat="server" Text="Import" OnClick="btnImport_Click" />  
  3. <br />  
  4. <asp:Label ID="Label1" runat="server" ForeColor="Blue" />  
  5. <br />  
  6. <asp:Label ID="Label2" runat="server" ForeColor="Green" />  
  7. <br />  
  8. <asp:Label ID="lblError" runat="server" ForeColor="Red" />  
After that we can now proceed with the codes for uploading and importing the CSV file to the SQL Server database. The following is the full code.
  1. using System;  
  2. using System.Configuration;  
  3. using System.Text;  
  4. using System.Data;  
  5. using System.Data.SqlClient;  
  6. using System.Data.OleDb;  
  7. using System.IO;  
  8. namespace WebFormsDemo  
  9. {  
  10.     public partial class CSVtoSQL: System.Web.UI.Page  
  11.     {  
  12.         private string GetConnectionString()   
  13.         {  
  14.             return ConfigurationManager.ConnectionStrings["DBConnection"].ConnectionString;  
  15.         }  
  16.         private void CreateDatabaseTable(DataTable dt, string tableName)   
  17.         {  
  18.             string sqlQuery = string.Empty;  
  19.             string sqlDBType = string.Empty;  
  20.             string dataType = string.Empty;  
  21.             int maxLength = 0;  
  22.             StringBuilder sb = new StringBuilder();  
  23.             sb.AppendFormat(string.Format("CREATE TABLE {0} (", tableName));  
  24.             for (int i = 0; i < dt.Columns.Count; i++)   
  25.             {  
  26.                 dataType = dt.Columns[i].DataType.ToString();  
  27.                 if (dataType == "System.Int32")  
  28.                 {  
  29.                     sqlDBType = "INT";  
  30.                 } else if (dataType == "System.String")  
  31.                 {  
  32.                     sqlDBType = "NVARCHAR";  
  33.                     maxLength = dt.Columns[i].MaxLength;  
  34.                 }  
  35.                 if (maxLength > 0)   
  36.                 {  
  37.                     sb.AppendFormat(string.Format("{0} {1} ({2}), ", dt.Columns[i].ColumnName, sqlDBType, maxLength));  
  38.                 }   
  39.                 else   
  40.                 {  
  41.                     sb.AppendFormat(string.Format("{0} {1},", dt.Columns[i].ColumnName, sqlDBType));  
  42.                 }  
  43.             }  
  44.             sqlQuery = sb.ToString();  
  45.             sqlQuery = sqlQuery.Trim().TrimEnd(',');  
  46.             sqlQuery = sqlQuery + " )";  
  47.             using(SqlConnection sqlConn = new SqlConnection(GetConnectionString()))   
  48.             {  
  49.                 sqlConn.Open();  
  50.                 using(SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn))  
  51.                 {  
  52.                     sqlCmd.ExecuteNonQuery();  
  53.                     sqlConn.Close();  
  54.                 }  
  55.             }  
  56.         }  
  57.         private void LoadDataToDatabase(string tableName, string fileFullPath, string delimeter)   
  58.         {  
  59.             string sqlQuery = string.Empty;  
  60.             StringBuilder sb = new StringBuilder();  
  61.             sb.AppendFormat(string.Format("BULK INSERT {0} ", tableName));  
  62.             sb.AppendFormat(string.Format(" FROM '{0}'", fileFullPath));  
  63.             sb.AppendFormat(string.Format(" WITH ( FIELDTERMINATOR = '{0}' , ROWTERMINATOR = '\n' )", delimeter));  
  64.             sqlQuery = sb.ToString();  
  65.             using(SqlConnection sqlConn = new SqlConnection(GetConnectionString()))   
  66.             {  
  67.                 sqlConn.Open();  
  68.                 using(SqlCommand sqlCmd = new SqlCommand(sqlQuery, sqlConn))   
  69.                 {  
  70.                     sqlCmd.ExecuteNonQuery();  
  71.                     sqlConn.Close();  
  72.                 }  
  73.             }  
  74.         }  
  75.         private void UploadAndProcessFile()   
  76.         {  
  77.             if (FileUpload1.HasFile)   
  78.             {  
  79.                 FileInfo fileInfo = new FileInfo(FileUpload1.PostedFile.FileName);  
  80.                 if (fileInfo.Name.Contains(".csv"))   
  81.                 {  
  82.                     string fileName = fileInfo.Name.Replace(".csv""").ToString();  
  83.                     string csvFilePath = Server.MapPath("UploadedCSVFiles") + "\\" + fileInfo.Name;  
  84.                     //Save the CSV file in the Server inside 'UploadedCSVFiles'   
  85.                     FileUpload1.SaveAs(csvFilePath);  
  86.                     //Fetch the location of CSV file   
  87.                     string filePath = Server.MapPath("UploadedCSVFiles") + "\\";  
  88.                     string strSql = "SELECT * FROM [" + fileInfo.Name + "]";  
  89.                     string strCSVConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";" + "Extended Properties='text;HDR=YES;'";  
  90.                     // load the data from CSV to DataTable   
  91.                     DataTable dtCSV = new DataTable();  
  92.                     DataTable dtSchema = new DataTable();  
  93.                     using(OleDbDataAdapter adapter = new OleDbDataAdapter(strSql, strCSVConnString))  
  94.                     {  
  95.                         adapter.FillSchema(dtCSV, SchemaType.Mapped);  
  96.                         adapter.Fill(dtCSV);  
  97.                     }  
  98.   
  99.                     if (dtCSV.Rows.Count > 0)  
  100.                     {  
  101.                         CreateDatabaseTable(dtCSV, fileName);  
  102.                         Label2.Text = string.Format("The table ({0}) has been successfully created to the database.", fileName);  
  103.                         string fileFullPath = filePath + fileInfo.Name;  
  104.                         LoadDataToDatabase(fileName, fileFullPath, ",");  
  105.                         Label1.Text = string.Format("({0}) records has been loaded to the table {1}.", dtCSV.Rows.Count, fileName);  
  106.                     }   
  107.                     else   
  108.                     {  
  109.                         lblError.Text = "File is empty.";  
  110.                     }  
  111.                 }   
  112.                 else   
  113.                 {  
  114.                     lblError.Text = "Unable to recognize file.";  
  115.                 }  
  116.             }  
  117.         }  
  118.         protected void btnImport_Click(object sender, EventArgs e)   
  119.         {  
  120.             UploadAndProcessFile();  
  121.         }  
  122.     }  
  123. }
The code above consists of the following four (4) private methods.

GetConnectionString() is a method that returns a string. This method basically gets the connection string that is configured from the web.config file.

CreateDatabaseTable() is method that accepts two (2) parameters that are the DataTable and the filename. This method is where the automatic creation of the database table is done based on the source DataTable and the filename of the CSV file.

LoadDataToDatabase() is a method that accepts three (3) parameters that are the tableName, fileFullPath and the delimeter value. This method is where the actual importing of data from the CSV to the SQL Server database table happens.

UploadAndProcessFile() handles the uploading of the CSV file to a specified location. This is also where the CreateDatabaseTable() and LoadDataToDatabase() are being called. If you notice, I also added some basic trappings and validations within that method.

Now let's create some simple data in a CSV format to test this importing utility. Just for the simplicity of this demo, let's create a CSV file and name it "Employee" and add the following data to it (take note of the format).

  1. Vincent Maverick,Durano,email1@email.com
  2. Vianne,Durano,email2@email.com
  3. Xhaiden,Durano,email3@email.com
  4. Angel Christine,Durano,emai4@email.com
  5. Kurt,Durano,emai5@email.com
  6. Erika,Bird,emai6@email.com
  7. Michelle,Lorenzana,emai7@email.com
  8. Lilibeth,Tree,emai8@email.com
  9. Bon,Bolger,email9@email.com
  10. Brian,Jones,email10@email.com

Now save the newly created CSV file in some location in your hard drive.

Running the page will display something like the following in the browser.

After browsing the CSV file



After importing



Now if we look at the database that we created earlier you'll notice that the Employee table has been successfully created with the imported data on it. See the following screenshot.



That's it! I hope you'll find this article useful.