SqlDataAdapter類別,是我們在學習ASP.NET資料庫裡兩大支柱的其中之一,會使用到它,也是因為要對Data進行操作,才會考慮使用到它,不然如果是單純取得資料,那一定是考慮SqlDataReader。
但我們在使用SqlDataAdapter類別「更新」資料時,有一個屬性非常重要,但也是大多沒有介紹,「UpdateBatchSize 屬性」,也是就是,我們原先如果更新了100筆資料,那就會一筆Update Query,一筆Update Query來對資料庫做更新資料的動作,這樣的方式不但沒有效率,又浪費資源,但這個UpdateBatchSize 屬性,能讓我們改變SqlDataAdapter類別的行為,讓我們使用「批次」的方來更新資料,但如我們有一個dap的SqlDataAdapter實體,所以我們可以設定「dap.UpdateBatchSize=10」,以10筆資料為一個單位來更新,經過這樣設定後,原本需要100次Query,只批次簡化為10次Query就結束了。
而相較於單一Query的更新方式,UpdateBatchSize當然可以大幅改善效能。而UpdateBatchSize的預設值正是1,而如果我們設定為0,那SqlDataAdapter物件會一次處理所有的Update命令。
也請小心,不要將UpdateBatchSize設的太大,每種資料庫批次處理的能力不同,上線前可多多測試,找出一個合理值,如果超出資料庫處理能力,SqlDataAdapter會拋出例外。
SqlBulkCopy類別,大量複製資料從A到B
昨天已經說了一個豬頭的故事,那今天就來寫個不豬頭的程式碼。
Default.aspx
Default.aspx.vb
程式目的:將程式本機資料庫中Share的資料大量複製到遠端Northwind資料庫中。
程式流程不會很難,
委派那一段可寫可不寫,在複製過程會觸發OnSqlRowsCopied事件,主要目的是顯示訊息讓使用者了解目前的進度。
如果兩端網路連線速度沒問題的話,十萬筆資料,都能在幾秒之內「秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~」,寫十萬筆Insert,有SqlBulkCopy不用,發瘋嗎。
Default.aspx
<form id="form1" runat="server"> <div> <asp:button id="btnBulkCopy" runat="server" text="Start Bulk Copy"></asp:button> <asp:label id="lblResult" runat="server"> <asp:label id="lblCounter" runat="server"> </div> </form>
Default.aspx.vb
程式目的:將程式本機資料庫中Share的資料大量複製到遠端Northwind資料庫中。
Imports System.Data
Imports System.Data.SqlClient
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub btnBulkCopy_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnBulkCopy.Click
'程式本機 Database Server Connection String
Dim shcs As New SqlConnectionStringBuilder
shcs.DataSource = ".\SQLEXPRESS"
shcs.InitialCatalog = "Share"
shcs.UserID = "bruce"
shcs.Password = "123456789"
'遠端Database Server Connection String
Dim ntcs As New SqlConnectionStringBuilder
ntcs.DataSource = "192.168.3.12\SQLEXPRESS"
ntcs.InitialCatalog = "Northwind"
ntcs.UserID = "bruce"
ntcs.Password = "987654321"
Dim shcmd As New SqlCommand
Dim shdr As SqlDataReader
Dim shconn As New SqlConnection(shcs.ConnectionString)
shcmd.CommandText = " SELECT ID, First_Name, Last_Name, 'CEO' as Source FROM MailingList"
shcmd.CommandType = CommandType.Text
shcmd.Connection = shconn
shcmd.Connection.Open()
'與遠端建立SqlBulkCopy實體
Dim ntbcp As New SqlBulkCopy(New SqlConnection(ntcs.ConnectionString))
'指定遠端的資料表名稱
ntbcp.DestinationTableName = "Employees"
'本機與遠端的Column對應,如本機與遠端的Schema一樣,可省略ColumnMappings
ntbcp.ColumnMappings.Add("ID", "EmployeeID")
ntbcp.ColumnMappings.Add("First_Name", "FirstName")
ntbcp.ColumnMappings.Add("Last_Name", "LastName")
'自定義欄位,把Source對應到Employees的Title欄位,所有欄位都會等於CEO
Dim TitleMapping As New SqlBulkCopyColumnMapping("Source", "Title")
ntbcp.ColumnMappings.Add(TitleMapping)
'TimeOut,單位秒
ntbcp.BulkCopyTimeout = 360
'多少筆發一次通知
ntbcp.NotifyAfter = 1000
'委派
AddHandler ntbcp.SqlRowsCopied, AddressOf OnSqlRowsCopied
'AddHandler ntbcp.SqlRowsCopied, New SqlRowsCopiedEventHandler(AddressOf OnSqlRowsCopied)
shdr = shcmd.ExecuteReader
Try
'執行WriteToServer,把本機資料(DataReader)大量複製到遠端資料庫
ntbcp.WriteToServer(shdr)
Catch ex As Exception
lblResult.Text = ex.Message
Finally
shdr.Close()
End Try
End Sub
Private Sub OnSqlRowsCopied(ByVal sender As Object, ByVal args As SqlRowsCopiedEventArgs)
'由於ntbcp.NotifyAfter的關係,每1000筆觸發一次
lblCounter.Text += args.RowsCopied.ToString() + " rows are copied.
"
End Sub
End Class
程式流程不會很難,
- 建立本機SqlConnection實體
- 建立遠端SqlBulkCopy實體(使用遠端Sqlconnection實體)
- 執行本機ExecuteReader方法,取得資料
- 執行SqlBulkCopy實體的WriteToServer方法,將DataReader寫到遠端Server去
委派那一段可寫可不寫,在複製過程會觸發OnSqlRowsCopied事件,主要目的是顯示訊息讓使用者了解目前的進度。
如果兩端網路連線速度沒問題的話,十萬筆資料,都能在幾秒之內「秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~秒殺~」,寫十萬筆Insert,有SqlBulkCopy不用,發瘋嗎。
ASP.NET WebForm命名注意
昨天在寫一支SqlBulkCopy類別的程式,說實在,這個類別可以寫的很簡單,也可以寫的很複雜。(廢話)
先簡單介紹一下,這個類別是.NET Framework 2.0所提供的一個類別,看命名就知道是在做「大量複製」,一般而言,例如,我們每一筆Insert就會對資料庫發出一筆Query,所以如我之前不是使用匯入方式來新增資料,而是使用複製、貼上就會浪費許多時間。
你簡單想像,SqlBulkCopy類別,就是「程式版的匯入功能」,讓你可以從多樣的資料來源,將你需要的大量資料批次匯入目的地資料庫。
但今天我不是要介紹SqlBulkCopy類別的功能,而且我在寫的這支程式,非常奇怪,不論我怎麼宣告,Dim ntbcp As New sqlBulkCopy(ConnectionString),就是會跑出來「Public Sub New()的引數太多」的錯誤訊息,查了許久,實在想不出什麼原因,上網也找不到什麼可參考的資料,所以就上MSDN請教大內高手。
在來回幾次後,終於發現問題,豬頭是自己產生的。我是豬頭。
這也給自己一個經驗,
先簡單介紹一下,這個類別是.NET Framework 2.0所提供的一個類別,看命名就知道是在做「大量複製」,一般而言,例如,我們每一筆Insert就會對資料庫發出一筆Query,所以如我之前不是使用匯入方式來新增資料,而是使用複製、貼上就會浪費許多時間。
你簡單想像,SqlBulkCopy類別,就是「程式版的匯入功能」,讓你可以從多樣的資料來源,將你需要的大量資料批次匯入目的地資料庫。
但今天我不是要介紹SqlBulkCopy類別的功能,而且我在寫的這支程式,非常奇怪,不論我怎麼宣告,Dim ntbcp As New sqlBulkCopy(ConnectionString),就是會跑出來「Public Sub New()的引數太多」的錯誤訊息,查了許久,實在想不出什麼原因,上網也找不到什麼可參考的資料,所以就上MSDN請教大內高手。
在來回幾次後,終於發現問題,豬頭是自己產生的。我是豬頭。
我新增的網頁名稱為「sqlBulkCopy.aspx」,所以產生了「Partial Class sqlBulkCopy」(s小寫),所以在程式中引用到自己(Web Form)的Class,而不是System.Data.SqlClient中SqlBulkCopy(S大寫)類別,所以當然有問題。
這也給自己一個經驗,
- .NET Framework類別,最好不要(一定不可以)拿來命名為網頁名稱
。 - 當局者迷。
使用SqlConnectionStringBuilder類別快速建立資料庫連線字串
我們ASP.NET網頁時,很少不用寫資料庫程式,而除了使用DataSource控制項外,如需要「靈活彈性」的話,那就不是DataSource控制項能提供了,所以等玩DataSource控制項一段時間後,還是不免要自行撰寫程式碼,而在寫資料庫連線程式時,常常會找筆記或參考程式複製、貼上那一段長長長長的ConnectionString,因為那一段ConectionString是字串,包在""之中,所以IntelliSense不會出現任何提示,你少打了一個字,打錯了一個字,也只能在執行網頁時才能除錯。也因為太長了,除非你天天打,打到都會背了,不然我看很少有人會去背那堆的參數。
其實在ASP.NET 2.0時就有提供一個非常好用的SqlConnectionStringBuilder類別,光看名子就知道,這是讓你拿來建立SQL連線字串,使用起來非常直覺,而且又提供IntelliSense,相信我,這可是能減輕腦負擔的好東西,如果你使用過一次SqlConnectionStringBuilder類別,大概就不會想回頭了,再去愛別人了。
這麼好用的東西,你在市面上一般的書本中是看不到哦,學起來,根本就不用背任何東西,IntelliSense選一選就完成了,不過,必要的資訊(就是後面的字串內容)還是要記一下。
其實在ASP.NET 2.0時就有提供一個非常好用的SqlConnectionStringBuilder類別,光看名子就知道,這是讓你拿來建立SQL連線字串,使用起來非常直覺,而且又提供IntelliSense,相信我,這可是能減輕腦負擔的好東西,如果你使用過一次SqlConnectionStringBuilder類別,大概就不會想回頭了,再去愛別人了。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'以下範例程式,未使用import System.Data.SqlClient
'原始:Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;User ID=bruce;Password=123456789
'以下使用SqlConnectionStringBuilder類別來建立ConnectionString
Dim CSBuilder As New System.Data.SqlClient.SqlConnectionStringBuilder
CSBuilder.DataSource = ".\SQLEXPRESS"
CSBuilder.InitialCatalog = "Northwind"
CSBuilder.UserID = "bruce"
CSBuilder.Password = "123456789"
CSBuilder.PersistSecurityInfo = True
'CSBuilder.ConnectionString取得連線字串,建立SqlConnection
Dim conn As New System.Data.SqlClient.SqlConnection(CSBuilder.ConnectionString)
'Other Code
End Sub
這麼好用的東西,你在市面上一般的書本中是看不到哦,學起來,根本就不用背任何東西,IntelliSense選一選就完成了,不過,必要的資訊(就是後面的字串內容)還是要記一下。
Microsoft Visual Studio International Feature Pack 2.0--在ASP.NET實作繁簡轉換
先看微軟的介紹:
而Visual Studio International Feature Pack 2.0是「擴充」之前1.0的功能,所以本身不含1.0的功能,如果想使用1.0提供的功能,可下載1.0進行安裝。
Microsoft Visual Studio International Pack 1.0 SR1
Microsoft Visual Studio International Feature Pack 2.0
如果你的網頁需要處理多國語言的問題,尤其是亞洲這個雙字元文字的問題,可一定要好好玩玩這個佛心級工具。想想,以前光一個「繁體轉簡體」的問題,就不知要花多少力,現在簡單幾行程式就可以完成了,.NET Framework是的越來越強大,真的是越來越愛了。
在Visual Studio International Pack 1.0 SR1的版本裡,我比較有興趣的是,CHTCHSConv.msi及EANumFormat.msi,
CHTCHSConv.msi
TCtoSC.aspx.vb
以上這支程式還可以用我們之前介紹使用Button裡的CommandName及CommandArgument來改寫。
EANumFormat.msi
將「C:\Program Files\Microsoft Visual Studio International Pack\East Asia Numeric Formatting Library」目錄之下的「EastAsiaNumericFormatter.dll」參考或複製到「Bin」之下。
EastAsiaNumericFormatting.aspx.vb
在Microsoft Visual Studio International Feature Pack 2.0的NumericConversion,新增對阿拉伯文的支援,安裝到可到「C:\Program Files\Microsoft Visual Studio International Feature Pack 2.0\NumericConversion」之下將「InternationalNumericFormatter.dll」參考或複製到「Bin」目錄之下,新增「InternationalNumericFormatter」類別,可進行對阿拉伯數字字串的設定。
舉個例子,以下是我的想法,我還沒有實作,但應該可行。
使用WebRequest類別將網頁資料讀進來,然後透過上述方法去轉換內容,然後再輸出,看你是要繁轉簡或簡轉繁,應該都不成問題才是。
Visual Studio International Feature Pack 2.0 擴充了先前 1.0 版的功能, 它提供了一組控制項和類別庫以幫助.NET開發人員建立符合國際化需求的應用程式。跟我們之前介紹使用資源檔的方式不同,它提供的是控制項(Controls)和類別庫(Class Library)來幫助.NET開發人員處理各種亞洲語系上的的文字、字串處理工作。
而Visual Studio International Feature Pack 2.0是「擴充」之前1.0的功能,所以本身不含1.0的功能,如果想使用1.0提供的功能,可下載1.0進行安裝。
Microsoft Visual Studio International Pack 1.0 SR1
Microsoft Visual Studio International Feature Pack 2.0
如果你的網頁需要處理多國語言的問題,尤其是亞洲這個雙字元文字的問題,可一定要好好玩玩這個佛心級工具。想想,以前光一個「繁體轉簡體」的問題,就不知要花多少力,現在簡單幾行程式就可以完成了,.NET Framework是的越來越強大,真的是越來越愛了。
在Visual Studio International Pack 1.0 SR1的版本裡,我比較有興趣的是,CHTCHSConv.msi及EANumFormat.msi,
CHTCHSConv.msi
Traditional Chinese to Simplified Chinese Conversion Library and Add-In Tool (中文繁簡轉換類別庫 及Visual Studio Add-In Tool工具):提供了一組類別庫以幫助程式開發人員在應用程式中轉換將中文繁體至中文簡體(或是中文簡體至中文繁體). 此轉換機制使用的內建於 Microsoft office 2007 的程式, 它的以進行詞對詞的轉換, 讓轉換的品質更好. 若使用者的系統中沒有安裝Microsoft office 2007 , 此類別庫將使用傳統的字對字轉換. 除此之外, 此元件也包括了一個 Visual Studio Add-In Tool 工具可以讓使用都直接轉換存在於資源檔中的中文字串.安裝後,將「C:\Program Files\Microsoft Visual Studio International Pack\Traditional Chinese to Simplified Chinese Conversion Library and Add-In Tool」之下的「ChineseConverter.dll」參考或複製到「Bin」目錄之下即可。
實作ChineseConverter
TCtoSC.aspx<form id="form1" runat="server"> <div> <asp:textbox id="tbxTCtoSC" runat="server"></asp:textbox> <asp:button id="btnTCtoSC" runat="server" text="繁體轉簡體"> <asp:label id="lblTCtoSC" runat="server"></asp:label> <asp:textbox id="tbxSCtoTC" runat="server"></asp:textbox> <asp:button id="btnSCtoTC" runat="server" text="簡體轉繁體"> <asp:label id="lblSCtoTC" runat="server"></asp:label> </asp:button></asp:button> </div> </form>
TCtoSC.aspx.vb
'繁簡轉換命名空間
Imports Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter
Partial Class Test_TCtoSC
Inherits System.Web.UI.Page
Protected Sub btnTCtoSC_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnTCtoSC.Click
If Me.tbxTCtoSC.Text.Length > 0 Then
Dim TWString As String = Me.tbxTCtoSC.Text
'使用ChineseConverter.Convert方法
'第一個參數是你要轉換的字串
'第二個參考是你要轉換目的語言
'TraditionalToSimplified是繁體轉換成簡體
Me.lblTCtoSC.Text = ChineseConverter.Convert(TWString, ChineseConversionDirection.TraditionalToSimplified)
End If
End Sub
Protected Sub btnSCtoTC_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSCtoTC.Click
If Me.tbxSCtoTC.Text.Length > 0 Then
Dim SCString As String = Me.tbxSCtoTC.Text
'使用ChineseConverter.Convert方法
'第一個參數是你要轉換的字串
'第二個參考是你要轉換目的語言
'SimplifiedToTraditional是簡體轉換成繁體
Me.lblSCtoTC.Text = ChineseConverter.Convert(SCString, ChineseConversionDirection.SimplifiedToTraditional)
End If
End Sub
End Class
以上這支程式還可以用我們之前介紹使用Button裡的CommandName及CommandArgument來改寫。
EANumFormat.msi
East Asia Numeric Formatting Library (亞洲語系的數值字串格式化類別庫):East Asia Numeric Formatting Library 提供了一組類別庫以幫助程式開發人員將數值資料格式化成亞洲語系的數值字串. 支援的亞洲語系包括了繁體中文, 簡體中文, 日文以及韓文.
將「C:\Program Files\Microsoft Visual Studio International Pack\East Asia Numeric Formatting Library」目錄之下的「EastAsiaNumericFormatter.dll」參考或複製到「Bin」之下。
實作EastAsiaNumericFormatter
EastAsiaNumericFormatting.aspx<form id="form1" runat="server"> <div> <asp:textbox id="tbxNumber" runat="server" tooltip="請輸入整數,例如:12345"></asp:textbox> <asp:button id="btnNumToChinese" runat="server" text="數字轉中文"> <asp:label id="lblNumtoChinese" runat="server"></asp:label> <asp:label id="lblNumtoJP" runat="server"></asp:label> </asp:button> </div> </form>
EastAsiaNumericFormatting.aspx.vb
'亞洲數字格式命名空間
Imports Microsoft.International.Formatters
'為了設定日文需要使用CultureInfo("ja")
Imports System.Globalization
Partial Class Test_EastAsiaNumericFormatting
Inherits System.Web.UI.Page
Protected Sub btnTCtoNum_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnNumToChinese.Click
If Me.tbxNumber.Text.Length > 0 Then
Dim ChangeNumber As Integer = Convert.ToInt32(Me.tbxNumber.Text)
Try
'會依瀏灠器做CultureInfo的選擇,如簡體瀏灠器則出現簡體中文的數字
Me.lblNumtoChinese.Text = String.Format(New EastAsiaNumericFormatter(), "數字的中文是:{0:L}", ChangeNumber)
'指定轉換的文字
'Me.lblNumtoJP.Text = "數字的日文是:" & EastAsiaNumericFormatter.FormatWithCulture("L", ChangeNumber, Nothing, New CultureInfo("ja"))
'FormatWithCulture(String, Object, IFormatProvider, CultureInfo)
Me.lblNumtoJP.Text = String.Format("數字的日文是:{0}", EastAsiaNumericFormatter.FormatWithCulture("L", ChangeNumber, Nothing, New CultureInfo("ja")))
Catch ex As Exception
Me.lblNumtoChinese.Text = "錯誤:" & ex.Message
End Try
End If
End Sub
End Class
在Microsoft Visual Studio International Feature Pack 2.0的NumericConversion,新增對阿拉伯文的支援,安裝到可到「C:\Program Files\Microsoft Visual Studio International Feature Pack 2.0\NumericConversion」之下將「InternationalNumericFormatter.dll」參考或複製到「Bin」目錄之下,新增「InternationalNumericFormatter」類別,可進行對阿拉伯數字字串的設定。
舉個例子,以下是我的想法,我還沒有實作,但應該可行。
使用WebRequest類別將網頁資料讀進來,然後透過上述方法去轉換內容,然後再輸出,看你是要繁轉簡或簡轉繁,應該都不成問題才是。
工具給各位,怎麼用就看各位的功力了,拿別人的努力讓自己更上一層樓。加油。
訂閱:
文章 (Atom)