sql server 使用SqlBulkCopy批量插入數據庫

sql server sqlbulkcopy 批量數據插入數據庫使用的是System.Data.SqlClient中的 SqlBulkCopy批量數據插入數據庫 sql

sql server 使用SqlBulkCopy批量插入數據庫數據庫

SqlBulkCopy位於位於命名空間System.Data.SqlClient下,主要功能是把其餘數據源(數據行DataRow,數據表DataTable,數據讀取器IDataReader等)的數據有效批量的導入到SQL Server表中的功能。相似與 Microsoft SQL Server 包中名爲 bcp 的命令行應用程序。可是使用 SqlBulkCopy 類能夠編寫託管代碼解決方案,性能上優於bcp命令行應用程序,更優於如Insert方式向SQL Server數據庫插入大量數據。所以SqlBulkCopy在應用到大批量數據的插入時很方便。服務器

下面時具體案例(包括Entityframwork Code First 生成數據庫,批量測試一萬條數據插入數據庫,讀取excel文件導入數據庫)app

一、新建項目BatchImportStaffEmployeeide

 

二、主窗體form1改爲FrmMain,post

三、NuGet添加EntityFramework,NPOI。EF用於生成數據庫,NPOI用於建立excel表格和讀取。性能

四、添加User類UserDBContext測試

User類以下:ui

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;this

namespace BatchImportStaffEmployee
{
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string PassWord { get; set; }
public string Address { get; set; }
public string Telephone { get; set; }
}
}

 

UserDBContext類以下:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;

namespace BatchImportStaffEmployee
{
public class UserDBContext : DbContext
{
//默認數據庫
//public UserDBContext()
//{
// //若是是第一次使用EF Code First,沒有進行任何數據庫配置,那麼默認是保存到「.\SQLEXPRESS」數據庫實例,若是未安裝「.\SQLEXPRESS」則默認使用LocalDb
//}

//指定數據庫
public UserDBContext(string connectString) : base(connectString)
{
//若是須要指定的服務器上建立數據庫,管理數據庫的話,如本機的數據庫實例,MyStudent數據庫,那麼這時須要配置App.Config中配置一個數據庫鏈接串,而後在咱們的數據庫上下文中指定這個鏈接名稱。
//< connectionStrings >
//< add name = "MyUserDB" connectionString = "Data Source=127.0.0.1;Database=MyUserDB;User ID=sa;PWD=123;" providerName = "System.Data.SqlClient" ></ add >
//</ connectionStrings >
}
public DbSet<User> Users { get; set; }
}
}

 五、添加文本標籤和按鈕,以下

六、配置App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<!--配置數據庫-->
<add name="MyUserDB" connectionString="Data Source=127.0.0.1;Database=MyUserDB;User ID=sa;PWD=123;" providerName="System.Data.SqlClient"></add>
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>

七、添加主窗體FrmMain對應事件以及方法,代碼以下

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace BatchImportStaffEmployee
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}

#region Method

/// <summary>
/// 生成一萬條測試數據
/// </summary>
/// <returns></returns>
public DataTable GetDataTableData()
{
List<User> userList = new List<User>();
for (int i = 0; i < 10000; i++)
{
User user = new User();
user.Name = "張三" + i;
user.PassWord = i.ToString();
user.Address = $"上海路{i}號";
user.Telephone = "18765443310";
userList.Add(user);
}
using (DataTable dt = new DataTable())
{
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("PassWord", typeof(string));
dt.Columns.Add("Address", typeof(string));
dt.Columns.Add("Telephone", typeof(string));
foreach (User user in userList)
{
DataRow dr = dt.NewRow();
dr["Name"] = user.Name;
dr["PassWord"] = user.PassWord;
dr["Address"] = user.Address;
dr["Telephone"] = user.Telephone;
dt.Rows.Add(dr);
}
return dt;
}
}

/// <summary>
/// 從文件中讀取數據,並生成數據表DataTable
/// </summary>
/// <param name="fileName">文件路徑</param>
/// <returns>數據表DataTable</returns>
public DataTable FillDataTable(string fileName)
{

if (string.IsNullOrEmpty(fileName))
{
return null;
}
try
{
DataTable table = new DataTable();
table.Columns.Add("UserID");//不爲空
table.Columns.Add("PlaceID");//不爲空
table.Columns.Add("UserNO");//不爲空
table.Columns.Add("UserName");
table.Columns.Add("Password");//不爲空
table.Columns.Add("UserType");
table.Columns.Add("Level");
table.Columns.Add("LevelCalcTime");
table.Columns.Add("UpdateTime");
table.Columns.Add("ManualLevel");
table.Columns.Add("EnableManualLevel");
table.Columns.Add("UserPic");
table.Columns.Add("UserMotto");
table.Columns.Add("UserCard");
table.Columns.Add("UserCardLocation");
table.Columns.Add("Position");
table.Columns.Add("WindowNo");
table.Columns.Add("WindowName");

using (StreamReader sr = new StreamReader(fileName, Encoding.Default))
{
while (!sr.EndOfStream)
{
DataRow dr = table.NewRow();
string readStr = sr.ReadLine();
if (readStr.StartsWith("1"))
{
string[] strs = readStr.Split(new char[] { '\t', '"' }, StringSplitOptions.RemoveEmptyEntries);

string startNum = strs[0];
string numArea = strs[1];
string numType = strs[2];

//往對應的 行中添加數據
dr["UserID"] = numType;//不爲空
dr["PlaceID"] = numType;//不爲空
dr["UserNO"] = numType;//不爲空
dr["UserName"] = numType;
dr["Password"] = numType;//不爲空
dr["UserType"] = numType;
dr["Level"] = numType;
dr["LevelCalcTime"] = numType;
dr["UpdateTime"] = numType;//不爲空
dr["ManualLevel"] = numType;//不爲空
dr["EnableManualLevel"] = numType;//不爲空
dr["UserPic"] = numType;
dr["UserMotto"] = numType;
dr["UserCard"] = numType;
dr["UserCardLocation"] = numType;
dr["Position"] = numType;
dr["WindowNo"] = numType;
dr["WindowName"] = numType;

table.Rows.Add(dr);//將建立的數據行添加到table中
}
}
}

return table;
}
catch (Exception ex)
{
MessageBox.Show($"FillDataTable失敗,緣由:{ex.ToString()}", "提示:");
throw;
}
}

/// <summary>
/// 將數據源導入數據庫中
/// </summary>
/// <param name="dataTable">數據源</param>
/// <returns>是否導入成功</returns>
public bool ImportDB(DataTable dataTable)
{
bool isOK = false;
string conStr = ConfigurationManager.ConnectionStrings["MyUserDB"].ConnectionString;
SqlConnection connection = new SqlConnection(conStr);
try
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conStr, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction))
{
bulkCopy.DestinationTableName = "[MyUserDB].[dbo].[Users]";//目標表,即要將數據插入到哪張表中去
bulkCopy.ColumnMappings.Add("Name", "Name");//數據源中的列名與目標表的屬性的映射關係
bulkCopy.ColumnMappings.Add("PassWord", "PassWord");
bulkCopy.ColumnMappings.Add("Address", "Address");
bulkCopy.ColumnMappings.Add("Telephone", "Telephone");
//DataTable dt = GetDataTableData();//數據源數據
DataTable dt = dataTable;
Stopwatch stopwatch = new Stopwatch();//秒錶進行時間的統計
stopwatch.Start();
bulkCopy.WriteToServer(dt);//將數據源數據寫入到數據庫中
this.rtb.Text = "插入數據所用時間:" + stopwatch.Elapsed.ToString();
isOK = true;
}
}
catch (Exception ex)
{
this.rtb.Text = $"插入數據所用時間:{ex.Message}";
isOK = false;
}
return isOK;
}

/// <summary>
/// 將數據源導入數據庫中
/// </summary>
/// <param name="dataTable">數據源</param>
/// <returns>是否導入成功</returns>
public bool ImportDatabase(DataTable dataTable)
{
bool isOK = false;
string conStr = ConfigurationManager.ConnectionStrings["MyUserDB"].ConnectionString;
try
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conStr, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction))
{
//目標表,即要將數據插入到哪張表中去
bulkCopy.DestinationTableName = "[MyUserDB].[dbo].[UserInfo]";
#region 數據源中的列名與目標表的屬性的映射關係
bulkCopy.ColumnMappings.Add("UserID", "UserID");
bulkCopy.ColumnMappings.Add("PlaceID", "PlaceID");
bulkCopy.ColumnMappings.Add("UserNO", "UserNO");
bulkCopy.ColumnMappings.Add("UserName", "UserName");
bulkCopy.ColumnMappings.Add("Password", "Password");
bulkCopy.ColumnMappings.Add("UserType", "UserType");
bulkCopy.ColumnMappings.Add("Level", "Level");
bulkCopy.ColumnMappings.Add("LevelCalcTime", "LevelCalcTime");
bulkCopy.ColumnMappings.Add("UpdateTime", "UpdateTime");
bulkCopy.ColumnMappings.Add("ManualLevel", "ManualLevel");
bulkCopy.ColumnMappings.Add("EnableManualLevel", "EnableManualLevel");
bulkCopy.ColumnMappings.Add("UserPic", "UserPic");
bulkCopy.ColumnMappings.Add("UserMotto", "UserMotto");
bulkCopy.ColumnMappings.Add("UserCard", "UserCard");
bulkCopy.ColumnMappings.Add("UserCardLocation", "UserCardLocation");
bulkCopy.ColumnMappings.Add("Position", "Position");
bulkCopy.ColumnMappings.Add("WindowNo", "WindowNo");
bulkCopy.ColumnMappings.Add("WindowName", "WindowName");
#endregion

//數據源數據
//DataTable dt = GetDataTableData();
DataTable dt = dataTable;
//秒錶進行時間的統計
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//將數據源數據寫入到數據庫中
bulkCopy.WriteToServer(dt);
this.rtb.Text = "將數據源導入數據庫中成功,插入數據所用時間:" + stopwatch.Elapsed.ToString();
isOK = true;
}
}
catch (Exception ex)
{
this.rtb.Text = $"將數據源導入數據庫中失敗,緣由:{ex.Message}";
isOK = false;
}
return isOK;
}

/// <summary>
/// 將數據源導入數據庫中
/// </summary>
/// <param name="dataTableReader">數據源</param>
/// <returns>是否導入成功</returns>
public bool ImportDatabae(DataTableReader dataTableReader)
{
bool isOK = false;
string conStr = ConfigurationManager.ConnectionStrings["MyUserDB"].ConnectionString;
try
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conStr, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction))
{
//目標表,即要將數據插入到哪張表中去
bulkCopy.DestinationTableName = "[MyUserDB].[dbo].[EvMS]";
#region 數據源中的列名與目標表的屬性的映射關係
bulkCopy.ColumnMappings.Add("UserID", "UserID");
bulkCopy.ColumnMappings.Add("PlaceID", "PlaceID");
bulkCopy.ColumnMappings.Add("UserNO", "UserNO");
bulkCopy.ColumnMappings.Add("UserName", "UserName");
bulkCopy.ColumnMappings.Add("Password", "Password");
bulkCopy.ColumnMappings.Add("UserType", "UserType");
bulkCopy.ColumnMappings.Add("Level", "Level");
bulkCopy.ColumnMappings.Add("LevelCalcTime", "LevelCalcTime");
bulkCopy.ColumnMappings.Add("UpdateTime", "UpdateTime");
bulkCopy.ColumnMappings.Add("ManualLevel", "ManualLevel");
bulkCopy.ColumnMappings.Add("EnableManualLevel", "EnableManualLevel");
bulkCopy.ColumnMappings.Add("UserPic", "UserPic");
bulkCopy.ColumnMappings.Add("UserMotto", "UserMotto");
bulkCopy.ColumnMappings.Add("UserCard", "UserCard");
bulkCopy.ColumnMappings.Add("UserCardLocation", "UserCardLocation");
bulkCopy.ColumnMappings.Add("Position", "Position");
bulkCopy.ColumnMappings.Add("WindowNo", "WindowNo");
bulkCopy.ColumnMappings.Add("WindowName", "WindowName");
#endregion
//數據源數據
//DataTable dt = GetDataTableData();
//秒錶進行時間的統計
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
//將數據源數據寫入到數據庫中
bulkCopy.WriteToServer(dataTableReader);
this.rtb.Text = "插入數據所用時間:" + stopwatch.Elapsed.ToString();
isOK = true;
}
}
catch (Exception ex)
{
this.rtb.Text = $"插入數據所用時間:{ex.Message}";
isOK = false;
}
return isOK;
}

/// <summary>
/// 將DataTable數據導入到excel中
/// </summary>
/// <param name="data">數據源</param>
/// <param name="fileName">保存excel文件路徑,包括名稱</param>
/// <returns></returns>
public bool DataTableToExcel(DataTable data, string fileName)
{
if (string.IsNullOrEmpty(fileName))
{
return false;
}

var fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
// .xlsx 是2007;.xls是 97-2003
IWorkbook workbook = new HSSFWorkbook();

try
{
ISheet sheet = workbook.CreateSheet(data.TableName);
int rowNO = 0;
//第一行建立 DataTable的列名
IRow row = sheet.CreateRow(0);
for (int i = 0; i < data.Columns.Count; ++i)
{
row.CreateCell(i).SetCellValue(data.Columns[i].ColumnName);
}
rowNO = 1;

for (int j = 0; j < data.Rows.Count; ++j)
{
IRow creatrow = sheet.CreateRow(rowNO);
for (int k = 0; k < data.Columns.Count; ++k)
{
creatrow.CreateCell(k).SetCellValue(data.Rows[j][k].ToString());
}
rowNO += 1; ;
}
workbook.Write(fs);
return true;
}
catch (Exception)
{
return false;
}
}

/// <summary>
/// 將excel中的數據導入到DataTable中
/// </summary>
/// <param name="sheetName">excel工做薄sheet的名稱</param>
/// <param name="firstRowIsColumn">第一行是不是DataTable的列名</param>
/// <returns>返回的DataTable</returns>
public DataTable ExcelToDataTable(string excelFileName, bool firstRowIsColumn)
{
DataTable data = new DataTable();
int startRow = 0;
try
{
var fs = new FileStream(excelFileName, FileMode.Open, FileAccess.Read);
IWorkbook workbook = new HSSFWorkbook(fs);
ISheet sheet = workbook.GetSheetAt(0);

if (sheet != null)
{
IRow firstRow = sheet.GetRow(0);
int cellCount = firstRow.LastCellNum;

//第一行是不是DataTable的列名
if (firstRowIsColumn)
{
for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
{
ICell cell = firstRow.GetCell(i);
if (cell != null)
{
string cellValue = cell.StringCellValue;
if (cellValue != null)
{
DataColumn column = new DataColumn(cellValue);
data.Columns.Add(column);
}
}
}
startRow = sheet.FirstRowNum + 1;
}
else
{
startRow = sheet.FirstRowNum;
}

//最後一列的標號
int rowCount = sheet.LastRowNum;
for (int i = startRow; i <= rowCount; ++i)
{
IRow row = sheet.GetRow(i);
if (row == null) continue; //沒有數據的行默認是null       

DataRow dataRow = data.NewRow();
for (int j = row.FirstCellNum; j < cellCount; ++j)
{
if (row.GetCell(j) != null)
{
dataRow[j] = row.GetCell(j).ToString();
}
else
{
dataRow[j] = null;
}
}
data.Rows.Add(dataRow);
}
}

return data;
}
catch (Exception ex)
{
MessageBox.Show($"Exception:{ex.Message}", "提示:");
return null;
}
}

#endregion

#region Event
private void BtnSelectFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "表格文檔|*.xls|文本文檔|*.txt|全部文件|*.*";

if (ofd.ShowDialog() != DialogResult.OK)
{
return;
}

this.tbxSelectFile.Text = ofd.FileName;
}

//從其餘數據源讀取數據導入到數據庫
private void BtnStartImport_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.tbxSelectFile.Text.Trim()))
{
MessageBox.Show("數據源文件選擇爲空,請從新選擇數據源文件。", "提示:");
this.tbxSelectFile.Focus();
return;
}

try
{
//DataTable table = FillDataTable(this.tbxSelectFile.Text);
DataTable table = ExcelToDataTable(this.tbxSelectFile.Text, true);
if (table != null)
{
bool isok = ImportDatabase(table);
if (isok)
{
MessageBox.Show($"批量導入{table.Rows.Count}條數據,導入成功!", "提示:");
}
}
else
{
MessageBox.Show($"批量導入數據失敗,緣由FillDataTable建立的表爲空。", "提示:");
}
}
catch (Exception ex)
{
MessageBox.Show($"批量導入數據失敗,緣由:{ex.ToString()}。", "提示:");
}
#region MyRegion
//string conStr = ConfigurationManager.ConnectionStrings["MyUserDB"].ConnectionString;
//SqlConnection connection = new SqlConnection(conStr);
//try
//{
// using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conStr, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction))
// {
// bulkCopy.DestinationTableName = "[MyUserDB].[dbo].[Users]";//目標表,就是說您將要將數據插入到哪一個表中去
// bulkCopy.ColumnMappings.Add("Name", "Name");//數據源中的列名與目標表的屬性的映射關係
// bulkCopy.ColumnMappings.Add("PassWord", "PassWord");
// bulkCopy.ColumnMappings.Add("Address", "Address");
// bulkCopy.ColumnMappings.Add("Telephone", "Telephone");
// DataTable dt = GetDataTableData();//數據源數據
// //bulkCopy.BatchSize = 3;
// Stopwatch stopwatch = new Stopwatch();//秒錶,該類能夠進行時間的統計
// stopwatch.Start();//秒錶開始
// bulkCopy.WriteToServer(dt);//將數據源數據寫入到目標表中
// this.rtb.Text = "插入數據所用時間:" + stopwatch.Elapsed.ToString();
// }
//}
//catch (Exception ex)
//{
// this.rtb.Text = $"插入數據所用時間:{ex.Message}";
//}
////this.rtb.Text = "插入數據插入成功";
#endregion
}

//測試生成數據庫
private void BtnCodeFirst_Click(object sender, EventArgs e)
{
try
{
User user = new User() { Name = "123", PassWord = "123678", Address = "長白山62號", Telephone = "52112314" };
UserDBContext userDBContext = new UserDBContext("MyUserDB");
userDBContext.Users.Add(user);
userDBContext.SaveChanges();

StringBuilder stringBuilder = new StringBuilder();

foreach (var item in userDBContext.Users)
{
stringBuilder.AppendLine($"用戶姓名:{item.Name}密碼:{item.PassWord},地址:{item.Address},電話:{item.Telephone}");
}
this.rtb.Text = stringBuilder.ToString();
MessageBox.Show(this.rtb.Text, "提示:");
}
catch (Exception ex)
{
MessageBox.Show($"錯誤信息:{ex}", "提示:");
}
}

//測試一萬條數據導入數據庫
private void BtnTestImportDatabase_Click(object sender, EventArgs e)
{
string conStr = ConfigurationManager.ConnectionStrings["MyUserDB"].ConnectionString;
SqlConnection connection = new SqlConnection(conStr);
try
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conStr, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.UseInternalTransaction))
{
bulkCopy.DestinationTableName = "dbo.[Users]";//目標表,就是說您將要將數據插入到哪一個表中去
bulkCopy.ColumnMappings.Add("Name", "Name");//數據源中的列名與目標表的屬性的映射關係
bulkCopy.ColumnMappings.Add("PassWord", "PassWord");
bulkCopy.ColumnMappings.Add("Address", "Address");
bulkCopy.ColumnMappings.Add("Telephone", "Telephone");
DataTable dt = GetDataTableData();//數據源數據 測試一萬條數據導入數據庫
//bulkCopy.BatchSize = 3;
Stopwatch stopwatch = new Stopwatch();//秒錶,該類能夠進行時間的統計
stopwatch.Start();//秒錶開始
bulkCopy.WriteToServer(dt);//將數據源數據寫入到目標表中
string outString = "插入數據插入成功,插入數據所用時間:" + stopwatch.Elapsed;
this.rtb.Text = outString;
MessageBox.Show(outString, "提示:");
}
}
catch (Exception ex)
{
this.rtb.Text = $"插入數據所用時間:{ex.Message}";
MessageBox.Show(this.rtb.Text, "提示:");
}
}
#endregion
}
}

 八、運行項目

九、注意項

a、excel表格文件的內容以下

b、sqlbulkcopy中添加映射的順序必須和數據庫中的列順序一致,也就時說,sqlbulkcopy的數據源的列順序,sqlbulkcopy映射順序和數據庫的列順序必須一致

 

c、App.config文件中數據鏈接字符串的配置

相關文章
相關標籤/搜索