1.創(chuàng)建表。
為了簡(jiǎn)單,表中只有一個(gè)字段,如下圖所示:
2.創(chuàng)建表值參數(shù)類型
我們打開查詢分析器,然后在查詢分析器中執(zhí)行下列代碼:
Create Type PassportTableType as Table(PassportKey nvarchar(50)執(zhí)行成功以后,我們打開企業(yè)管理器,按順序依次展開下列節(jié)點(diǎn)--數(shù)據(jù)庫(kù)、展開可編程性、類型、用戶自定義表類型,就可以看到我們創(chuàng)建好的表值類型了如下圖所示:
說明我們創(chuàng)建表值類型成功了。
3.編寫存儲(chǔ)過程
存儲(chǔ)過程的代碼為:
復(fù)制代碼 代碼如下:
USE [TestInsert]
GO
/****** Object: StoredProcedure [dbo].[CreatePassportWithTVP] Script Date: 03/02/2010 00:14:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Kevin>
-- Create date: <2010-3-1>
-- Description: <創(chuàng)建通行證>
-- =============================================
Create PROCEDURE [dbo].[CreatePassportWithTVP]
@TVP PassportTableType readonly
AS
BEGIN
SET NOCOUNT ON;
Insert into Passport(PassportKey) select PassportKey from @TVP
END
復(fù)制代碼 代碼如下:
using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
using com.DataAccess;
namespace ConsoleAppInsertTest
{
class Program
{
static string connectionString = SqlHelper.ConnectionStringLocalTransaction; //數(shù)據(jù)庫(kù)連接字符串
static int count = 1000000; //插入的條數(shù)
static void Main(string[] args)
{
//long commonInsertRunTime = CommonInsert();
//Console.WriteLine(string.Format("普通方式插入{1}條數(shù)據(jù)所用的時(shí)間是{0}毫秒", commonInsertRunTime, count));
long sqlBulkCopyInsertRunTime = SqlBulkCopyInsert();
Console.WriteLine(string.Format("使用SqlBulkCopy插入{1}條數(shù)據(jù)所用的時(shí)間是{0}毫秒", sqlBulkCopyInsertRunTime, count));
long TVPInsertRunTime = TVPInsert();
Console.WriteLine(string.Format("使用表值方式(TVP)插入{1}條數(shù)據(jù)所用的時(shí)間是{0}毫秒", TVPInsertRunTime, count));
}
/// <summary>
/// 普通調(diào)用存儲(chǔ)過程插入數(shù)據(jù)
/// </summary>
/// <returns></returns>
private static long CommonInsert()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string passportKey;
for (int i = 0; i < count; i++)
{
passportKey = Guid.NewGuid().ToString();
SqlParameter[] sqlParameter = { new SqlParameter("@passport", passportKey) };
SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, "CreatePassport", sqlParameter);
}
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
/// <summary>
/// 使用SqlBulkCopy方式插入數(shù)據(jù)
/// </summary>
/// <param></param>
/// <returns></returns>
private static long SqlBulkCopyInsert()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
DataTable dataTable = GetTableSchema();
string passportKey;
for (int i = 0; i < count; i++)
{
passportKey = Guid.NewGuid().ToString();
DataRow dataRow = dataTable.NewRow();
dataRow[0] = passportKey;
dataTable.Rows.Add(dataRow);
}
SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(connectionString);
sqlBulkCopy.DestinationTableName = "Passport";
sqlBulkCopy.BatchSize = dataTable.Rows.Count;
SqlConnection sqlConnection = new SqlConnection(connectionString);
sqlConnection.Open();
if (dataTable!=null && dataTable.Rows.Count!=0)
{
sqlBulkCopy.WriteToServer(dataTable);
}
sqlBulkCopy.Close();
sqlConnection.Close();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
private static long TVPInsert()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
DataTable dataTable = GetTableSchema();
string passportKey;
for (int i = 0; i < count; i++)
{
passportKey = Guid.NewGuid().ToString();
DataRow dataRow = dataTable.NewRow();
dataRow[0] = passportKey;
dataTable.Rows.Add(dataRow);
}
SqlParameter[] sqlParameter = { new SqlParameter("@TVP", dataTable) };
SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, "CreatePassportWithTVP", sqlParameter);
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
private static DataTable GetTableSchema()
{
DataTable dataTable = new DataTable();
dataTable.Columns.AddRange(new DataColumn[] { new DataColumn("PassportKey") });
return dataTable;
}
}
}
比較神秘的代碼其實(shí)就下面這兩行,該代碼是將一個(gè)dataTable做為參數(shù)傳給了我們的存儲(chǔ)過程。簡(jiǎn)單吧。
SqlParameter[] sqlParameter = { new SqlParameter("@TVP", dataTable) };通過以上測(cè)試方案,不難發(fā)現(xiàn),技術(shù)方案二的優(yōu)勢(shì)還是蠻高的。無(wú)論是從通用性還是從性能上考慮,都應(yīng)該是
優(yōu)先被選擇的,還有一點(diǎn),它的技術(shù)復(fù)雜度要比技術(shù)方案三要簡(jiǎn)單一些,
設(shè)想我們把所有表都創(chuàng)建一遍表值類型,工作量還是有的。因此,我依然堅(jiān)持我開始時(shí)的決定,
向公司推薦使用第二種技術(shù)方案。
寫到此,本文就算完了,但是對(duì)新技術(shù)的鉆研仍然還在不斷繼續(xù)。要做的東西還是挺多的。
為了方便大家學(xué)習(xí)和交流,代碼文件已經(jīng)打包并上傳了,歡迎共同學(xué)習(xí)探討。
代碼下載
作者:深山老林
出處:
新聞熱點(diǎn)
疑難解答
圖片精選