Crystal Reports for Visual Studio 2008 requires a "runtime" to load reports on a client machine. This "runtime" can be found in this location on the development machine.
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\CrystalReports10_5"
"CRRedist2008_x86.msi" (for 32bit)
"CRRedist2008_x64.msi" (for 64bit)
Running this install package will install the files necessary to run open forms using Crystal Reports for Visual Studio 2008 (version 10.5 in the IDE). This is NOT the required "Runtime" for Crystal Reports 2008 (which is version 12).
2010年9月30日 星期四
2010年9月29日 星期三
Windows各版本支援最大記憶清單
最近的RAM愈來愈便宜了,但卻不知道自己的OS有沒有辨法支援到那麼大,希望以下的資訊對大家有幫助.
Maximum Ram supported list By Windows
作業系統版本 32位元 64位元
Windows Server 2008
Windows Server 2008 Datacenter (full installation) 64 GB 2 TB
Windows Server 2008 Datacenter (Server Core installation) 64 GB 2 TB
Windows Server 2008 Enterprise 64 GB 2 TB
Windows Server 2008 HPC Edition 不適用 128 GB
Windows Server 2008 Standard 4 GB 32 GB
Windows Server 2008 for Itanium-Based Systems 不適用 2 TB
Windows Web Server 2008 4 GB 32 GB
Windows 7
Windows Home Basic 4 GB 8 GB
Windows Starter 4 GB 8 GB
Windows Home Premium 4 GB 16 GB
Windows Professional 4 GB 192 GB
Windows Enterprise & Ultimate 4 GB 192 GB
Windows Vista
Windows Vista Ultimate 4 GB 128 GB
Windows Vista Enterprise 4 GB 128 GB
Windows Vista Business 4 GB 128 GB
Windows Vista Home Premium 4 GB 16 GB
Windows Vista Home Basic 4 GB 8 GB
Windows Vista Starter 1 GB 不適用
Windows Server 2003
Windows Server 2003 with Service Pack 2 (SP2), Datacenter Edition 128 GB
64 GB with 4GT 2 TB
Windows Server 2003 with Service Pack 2 (SP2), Enterprise Edition 64 GB 2 TB
Windows Storage Server 2003, Enterprise Edition 8 GB 不適用
Windows Storage Server 2003 4 GB 不適用
Windows Server 2003 R2 Datacenter Edition
Windows Server 2003 with Service Pack 1 (SP1), Datacenter Edition 128 GB
64 GB with 4GT 1 TB
Windows Server 2003 R2 Enterprise Edition
Windows Server 2003 with Service Pack 1 (SP1), Enterprise Edition 64 GB
16 GB with 4GT 1 TB
Windows Server 2003 R2 Standard Edition
Windows Server 2003, Standard Edition SP1
Windows Server 2003, Standard Edition SP2 4 GB 32 GB
Windows Server 2003, Datacenter Edition 128 GB
16 GB with 4GT 512 GB
Windows Server 2003, Enterprise Edition 32 GB
16 GB with 4GT 64 GB
Windows Server 2003, Standard Edition 4 GB 16 GB
Windows Server 2003, Web Edition 2 GB 不適用
Windows Small Business Server 2003 4 GB 不適用
Windows Compute Cluster Server 2003 不適用 32 GB
Windows XP
Windows XP Professional 4 GB 128 GB
Windows XP Home Edition 4 GB 128 GB
Windows XP Starter Edition 512 MB 不適用
Windows 2000
Windows 2000 Professional 4 GB 不適用
Windows 2000 Server 4 GB 不適用
Windows 2000 Advanced Server 8 GB 不適用
Windows 2000 Datacenter Server 32 GB 不適用
Windows NT
Windows NT Workstation 4 GB 不適用
Windows NT Server 4 GB 不適用
Windows NT Enterprise Server 4 GB 不適用
Windows Previous Version
Windows 95 2 GB 不適用
Windows 98 2 GB 不適用
Windows ME 2 GB 不適用
Windows 3.1x Standard Edition 256 MB 不適用
DOS 64 MB 不適用
Maximum Ram supported list By Windows
作業系統版本 32位元 64位元
Windows Server 2008
Windows Server 2008 Datacenter (full installation) 64 GB 2 TB
Windows Server 2008 Datacenter (Server Core installation) 64 GB 2 TB
Windows Server 2008 Enterprise 64 GB 2 TB
Windows Server 2008 HPC Edition 不適用 128 GB
Windows Server 2008 Standard 4 GB 32 GB
Windows Server 2008 for Itanium-Based Systems 不適用 2 TB
Windows Web Server 2008 4 GB 32 GB
Windows 7
Windows Home Basic 4 GB 8 GB
Windows Starter 4 GB 8 GB
Windows Home Premium 4 GB 16 GB
Windows Professional 4 GB 192 GB
Windows Enterprise & Ultimate 4 GB 192 GB
Windows Vista
Windows Vista Ultimate 4 GB 128 GB
Windows Vista Enterprise 4 GB 128 GB
Windows Vista Business 4 GB 128 GB
Windows Vista Home Premium 4 GB 16 GB
Windows Vista Home Basic 4 GB 8 GB
Windows Vista Starter 1 GB 不適用
Windows Server 2003
Windows Server 2003 with Service Pack 2 (SP2), Datacenter Edition 128 GB
64 GB with 4GT 2 TB
Windows Server 2003 with Service Pack 2 (SP2), Enterprise Edition 64 GB 2 TB
Windows Storage Server 2003, Enterprise Edition 8 GB 不適用
Windows Storage Server 2003 4 GB 不適用
Windows Server 2003 R2 Datacenter Edition
Windows Server 2003 with Service Pack 1 (SP1), Datacenter Edition 128 GB
64 GB with 4GT 1 TB
Windows Server 2003 R2 Enterprise Edition
Windows Server 2003 with Service Pack 1 (SP1), Enterprise Edition 64 GB
16 GB with 4GT 1 TB
Windows Server 2003 R2 Standard Edition
Windows Server 2003, Standard Edition SP1
Windows Server 2003, Standard Edition SP2 4 GB 32 GB
Windows Server 2003, Datacenter Edition 128 GB
16 GB with 4GT 512 GB
Windows Server 2003, Enterprise Edition 32 GB
16 GB with 4GT 64 GB
Windows Server 2003, Standard Edition 4 GB 16 GB
Windows Server 2003, Web Edition 2 GB 不適用
Windows Small Business Server 2003 4 GB 不適用
Windows Compute Cluster Server 2003 不適用 32 GB
Windows XP
Windows XP Professional 4 GB 128 GB
Windows XP Home Edition 4 GB 128 GB
Windows XP Starter Edition 512 MB 不適用
Windows 2000
Windows 2000 Professional 4 GB 不適用
Windows 2000 Server 4 GB 不適用
Windows 2000 Advanced Server 8 GB 不適用
Windows 2000 Datacenter Server 32 GB 不適用
Windows NT
Windows NT Workstation 4 GB 不適用
Windows NT Server 4 GB 不適用
Windows NT Enterprise Server 4 GB 不適用
Windows Previous Version
Windows 95 2 GB 不適用
Windows 98 2 GB 不適用
Windows ME 2 GB 不適用
Windows 3.1x Standard Edition 256 MB 不適用
DOS 64 MB 不適用
Programming Environments
Programming Environments
Programming Environments
Delphi Win32
C++Builder 2010
Borland C++ Builder
Microsoft Visual C++ (MFC)
Microsoft Visual C++/CLI
Microsoft Visual C++ .NET
SharpDevelop
Microsoft Visual C#
Delphi .NET
Microsoft Visual F#
Microsoft Visual Basic
Microsoft Visual Basic 6
Programming Environments
Delphi Win32
C++Builder 2010
Borland C++ Builder
Microsoft Visual C++ (MFC)
Microsoft Visual C++/CLI
Microsoft Visual C++ .NET
SharpDevelop
Microsoft Visual C#
Delphi .NET
Microsoft Visual F#
Microsoft Visual Basic
Microsoft Visual Basic 6
2010年9月27日 星期一
2010年9月26日 星期日
透過IHttpHandler讓某虛擬目錄中檔案(例如Test.txt)必須登入才可瀏覽或下載
1.撰寫IHttpHandler處理這些檔案類型
2.設定Web.Config來註冊IHttpHandler,並且設定該資料夾Deny Users="?"
3.在IIS中註冊這些副檔名由【aspnet_isapi.dll】處理(這樣才能啟動IHttpHandler)
新增一個類別(Class),命名為CFileSafe.vb,
Imports命名空間System.Web
Implements IHttpHandler,
VS自動會產生IsReusable的Property與ProcessRequest的Sub,
接著撰寫處理Request的內容,判斷傳入的副檔名,依據不同的副檔名,
指定不同的Response.ContentType
Imports Microsoft.VisualBasic
Imports System.Web
Public Class CFileSafe
Implements IHttpHandler
Public ReadOnly Property IsReusable() ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
End Get
End Property
Public Sub ProcessRequest() Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim FileName As String = context.Request.FilePath
Dim tmpS() As String
tmpS = FileName.Split(".")
Dim FileExten As String = LCase(tmpS(UBound(tmpS)))
Dim GetContentType As Boolean = False
Select Case FileExten
Case "txt"
context.Response.ContentType = "text/plain"
GetContentType = True
Case "doc"
context.Response.ContentType = "application/msword"
GetContentType = True
Case "xls"
context.Response.ContentType = "application/ms-excel"
GetContentType = True
Case "ppt"
context.Response.ContentType = "application/vnd.ms-powerpoint"
GetContentType = True
Case "pdf"
context.Response.ContentType = "application/pdf"
GetContentType = True
Case "zip"
context.Response.ContentType = "application/x-zip-compressed"
GetContentType = True
Case "gif"
context.Response.ContentType = "image/gif"
GetContentType = True
Case "tif"
context.Response.ContentType = "image/tiff"
GetContentType = True
Case "jpg"
context.Response.ContentType = "image/jpeg"
GetContentType = True
End Select
If GetContentType Then
context.Response.TransmitFile(context.Request.FilePath)
'context.Response.Write(FileExten)
Else
'context.Response.Write(FileExten)
context.Response.Write("未設定檔案格式【" & FileExten & "】!!")
End If
End Sub
End Class
增加資料夾(Files),並新增Web.config來註冊IHttpHandler
最後的一個步驟→設定這些檔案格式給ISAPI處理
開啟IIS,瀏覽到我們ASP.NET應用程式中的Files資料夾,點選滑鼠右鍵→內容。
當我們要設定ISAPI的時候發現,由於他不是個應用程式,所以無法針對Files設定ISAPI,
此時我們可以先暫時把該資料夾建立為應用程式,讓他可以設定,等設定完成後再把應用程式移除即可。
接著進入設定,來看看副檔名aspx的設定為何??
將處理aspx的aspnet_isapi.dll路徑複製下來,等一下用相同的檔案來處理我們要處理的副檔名
接著新增一個副檔名的處理,我們舉txt來當作範例
1.設執行檔...aspnet_isapi.dll
2.設副檔名txt
3.選所有的指令動詞
4.取消確認檔案是否存在
接著把其他的副檔名用相同的方式設定,這個部份的畫面就省略了。
最後,Files其實不是個應用程式所以記得把應用程式移除
經過以上的設定後,再來測試看看就會發現,當瀏覽Files下的Test.txt的時候,
系統會自動導向到Login.aspx要求登入,登入完成後,自動再導回Test.txt的內容進行瀏覽。
接著測試zip也一樣,在未登入的狀況下,會要求使用者進行登入,登入完成後,
就會出現下載儲存的對話方塊。
2.設定Web.Config來註冊IHttpHandler,並且設定該資料夾Deny Users="?"
3.在IIS中註冊這些副檔名由【aspnet_isapi.dll】處理(這樣才能啟動IHttpHandler)
新增一個類別(Class),命名為CFileSafe.vb,
Imports命名空間System.Web
Implements IHttpHandler,
VS自動會產生IsReusable的Property與ProcessRequest的Sub,
接著撰寫處理Request的內容,判斷傳入的副檔名,依據不同的副檔名,
指定不同的Response.ContentType
Imports Microsoft.VisualBasic
Imports System.Web
Public Class CFileSafe
Implements IHttpHandler
Public ReadOnly Property IsReusable() ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
Get
End Get
End Property
Public Sub ProcessRequest() Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
Dim FileName As String = context.Request.FilePath
Dim tmpS() As String
tmpS = FileName.Split(".")
Dim FileExten As String = LCase(tmpS(UBound(tmpS)))
Dim GetContentType As Boolean = False
Select Case FileExten
Case "txt"
context.Response.ContentType = "text/plain"
GetContentType = True
Case "doc"
context.Response.ContentType = "application/msword"
GetContentType = True
Case "xls"
context.Response.ContentType = "application/ms-excel"
GetContentType = True
Case "ppt"
context.Response.ContentType = "application/vnd.ms-powerpoint"
GetContentType = True
Case "pdf"
context.Response.ContentType = "application/pdf"
GetContentType = True
Case "zip"
context.Response.ContentType = "application/x-zip-compressed"
GetContentType = True
Case "gif"
context.Response.ContentType = "image/gif"
GetContentType = True
Case "tif"
context.Response.ContentType = "image/tiff"
GetContentType = True
Case "jpg"
context.Response.ContentType = "image/jpeg"
GetContentType = True
End Select
If GetContentType Then
context.Response.TransmitFile(context.Request.FilePath)
'context.Response.Write(FileExten)
Else
'context.Response.Write(FileExten)
context.Response.Write("未設定檔案格式【" & FileExten & "】!!")
End If
End Sub
End Class
增加資料夾(Files),並新增Web.config來註冊IHttpHandler
最後的一個步驟→設定這些檔案格式給ISAPI處理
開啟IIS,瀏覽到我們ASP.NET應用程式中的Files資料夾,點選滑鼠右鍵→內容。
當我們要設定ISAPI的時候發現,由於他不是個應用程式,所以無法針對Files設定ISAPI,
此時我們可以先暫時把該資料夾建立為應用程式,讓他可以設定,等設定完成後再把應用程式移除即可。
接著進入設定,來看看副檔名aspx的設定為何??
將處理aspx的aspnet_isapi.dll路徑複製下來,等一下用相同的檔案來處理我們要處理的副檔名
接著新增一個副檔名的處理,我們舉txt來當作範例
1.設執行檔...aspnet_isapi.dll
2.設副檔名txt
3.選所有的指令動詞
4.取消確認檔案是否存在
接著把其他的副檔名用相同的方式設定,這個部份的畫面就省略了。
最後,Files其實不是個應用程式所以記得把應用程式移除
經過以上的設定後,再來測試看看就會發現,當瀏覽Files下的Test.txt的時候,
系統會自動導向到Login.aspx要求登入,登入完成後,自動再導回Test.txt的內容進行瀏覽。
接著測試zip也一樣,在未登入的狀況下,會要求使用者進行登入,登入完成後,
就會出現下載儲存的對話方塊。
2010年9月25日 星期六
FileUpload to db 防止 null 問題
If fileUpload1.HasFile Then
Dim File As HttpPostedFile = fileUpload1.PostedFile
imgByte = New [Byte](File.ContentLength - 1) {}
File.InputStream.Read(imgByte, 0, File.ContentLength)
myNews.Image = imgByte
Else
myNews.Image = Nothing
end if
---
以上code重點在必須加myNews.Image = Nothing
Dim File As HttpPostedFile = fileUpload1.PostedFile
imgByte = New [Byte](File.ContentLength - 1) {}
File.InputStream.Read(imgByte, 0, File.ContentLength)
myNews.Image = imgByte
Else
myNews.Image = Nothing
end if
---
以上code重點在必須加myNews.Image = Nothing
ASP.NET 使用 Greybox 說明
引用來原處
=========
Greybox除了可以用於圖片和網頁外、連 flash、影片都可以顯示在 Lightbox 彈出的方框裡面。
下載程式(http://orangoo.com/labs/GreyBox/Download/)
=========
Greybox除了可以用於圖片和網頁外、連 flash、影片都可以顯示在 Lightbox 彈出的方框裡面。
下載程式(http://orangoo.com/labs/GreyBox/Download/)
連結MYSQL
Dim conn1 As MySqlConnection = New MySqlConnection("Database=DBName; Data Source=HostName; User Id=Account; Password=Password; CharSet=big5;")
Dim DBstr1 As String = "Select * From ABC Order by ID"
Dim DA1 As MySqlDataAdapter = New MySqlDataAdapter(DBstr1, conn1)
Dim DS1 As DataSet = New DataSet
Try
conn1.Open()
DA1.Fill(DS1, "Data")
Catch ex As Exception
MsgBox(ex.Message)
Finally
conn1.Close()
End Try
Dim DBstr1 As String = "Select * From ABC Order by ID"
Dim DA1 As MySqlDataAdapter = New MySqlDataAdapter(DBstr1, conn1)
Dim DS1 As DataSet = New DataSet
Try
conn1.Open()
DA1.Fill(DS1, "Data")
Catch ex As Exception
MsgBox(ex.Message)
Finally
conn1.Close()
End Try
在vb.net下寫多執行緒的程式
Public Class Count1
Public CountTo as Integer
' 當程序處理完畢,透過這個method來讓對方知道你已經做完了
Public event FinishedCounting(ByVal NumberOfMatches as Integer)
Sub Count()
Dim ind,tot as Integer
tot=0
For ind=1 to CountTo
tot+=1
Next ind
' raise一個事件出來說已經做完了
' 並將處理完的值回傳回去
RaiseEvent FinishedCounting(tot)
End Sub
End Class
' 這一段程式碼就是用來執行呼叫tread
Dim counter1 as new Count1()
Dim Thread1 as New System.Threading.Thread(Addressof counter.Count)
Private Sub LetMeCallThread(Byval counter as Integer)
counter1.CountTo=counter
' 與物件之間的Call Back機制, 建立handler (Call Back的function)
' 當物件Raise該事件時,可以透過該function取得結果
AddHandler counter1.FinishedCounting,AddressOf FinishedCountingEventHandler
' 啟動執行緖
Thread1.Start()
End Sub
' 當Thread程式執行完畢(這就是所謂的CallBack機制)
Sub FinishedCountingEventHandler(ByVal Count as Integer)
msgbox(Count)
End Sub
Public CountTo as Integer
' 當程序處理完畢,透過這個method來讓對方知道你已經做完了
Public event FinishedCounting(ByVal NumberOfMatches as Integer)
Sub Count()
Dim ind,tot as Integer
tot=0
For ind=1 to CountTo
tot+=1
Next ind
' raise一個事件出來說已經做完了
' 並將處理完的值回傳回去
RaiseEvent FinishedCounting(tot)
End Sub
End Class
' 這一段程式碼就是用來執行呼叫tread
Dim counter1 as new Count1()
Dim Thread1 as New System.Threading.Thread(Addressof counter.Count)
Private Sub LetMeCallThread(Byval counter as Integer)
counter1.CountTo=counter
' 與物件之間的Call Back機制, 建立handler (Call Back的function)
' 當物件Raise該事件時,可以透過該function取得結果
AddHandler counter1.FinishedCounting,AddressOf FinishedCountingEventHandler
' 啟動執行緖
Thread1.Start()
End Sub
' 當Thread程式執行完畢(這就是所謂的CallBack機制)
Sub FinishedCountingEventHandler(ByVal Count as Integer)
msgbox(Count)
End Sub
Fileupload 上傳
Dim FileSplit() As String = Split(Me.FileUpload1.FileName, ".")
Dim nx As String = FileSplit(FileSplit.Length - 1)'取得檔案副檔名
Dim fileName As String = Now.ToString("yyyyMMdd")'取得日期
Dim ano As Int16 = (101) '流水號預設值
Dim Path As String = Server.MapPath("~/UpFile/")
Do While File.Exists(Path & fileName & ano & "." & nx) '判斷是否有相同檔名存在並累加流水編號
ano = ano + 1
Loop
Dim cn As New Data.SqlClient.SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True")
Dim strsql As String = "Insert Into database (filelink) values (@url)"
Dim cmd As New Data.SqlClient.SqlCommand(strsql, cn)
Dim FileOk As Boolean = False '宣告一個FileOk用來判別是否上傳成功,預設為False
Dim fileExtension As String '宣告一個變數存放檔案格式(副檔名)
Dim i As Integer
If Me.FileUpload1.HasFile Then '透過HasFile判斷有檔案上傳
fileExtension = IO.Path.GetExtension(Me.FileUpload1.FileName).ToLower '取得檔案格式
Dim allowedExtensions As String() = {".jpg", ".jpeg", ".png", ".gif", ".pdf"} '定義允許的檔案格式
For i = 0 To allowedExtensions.Length - 1 '逐一檢查允許的格式中是否有上傳的格式
If fileExtension = allowedExtensions(i) Then
FileOk = True
End If
Next
If FileOk Then
Try
Me.FileUpload1.PostedFile.SaveAs(Path & fileName & ano & "." & nx) '將上傳的檔案儲存
Me.Label1.Text = "Upload Success!!" '傳回成功
cn.Open()
cmd.Parameters.Add("@url", System.Data.SqlDbType.VarChar).Value = "~/UpFile/" & fileName & ano & "." & nx
cmd.ExecuteNonQuery()
cn.Close()
Catch ex As Exception
Me.Label1.Text = "Upload False!!
" + ex.Message
End Try
Else
Me.Label1.Text = "檔案上傳失敗,請確認檔案格式是否正確!!"
End If
End If
Dim nx As String = FileSplit(FileSplit.Length - 1)'取得檔案副檔名
Dim fileName As String = Now.ToString("yyyyMMdd")'取得日期
Dim ano As Int16 = (101) '流水號預設值
Dim Path As String = Server.MapPath("~/UpFile/")
Do While File.Exists(Path & fileName & ano & "." & nx) '判斷是否有相同檔名存在並累加流水編號
ano = ano + 1
Loop
Dim cn As New Data.SqlClient.SqlConnection("Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True")
Dim strsql As String = "Insert Into database (filelink) values (@url)"
Dim cmd As New Data.SqlClient.SqlCommand(strsql, cn)
Dim FileOk As Boolean = False '宣告一個FileOk用來判別是否上傳成功,預設為False
Dim fileExtension As String '宣告一個變數存放檔案格式(副檔名)
Dim i As Integer
If Me.FileUpload1.HasFile Then '透過HasFile判斷有檔案上傳
fileExtension = IO.Path.GetExtension(Me.FileUpload1.FileName).ToLower '取得檔案格式
Dim allowedExtensions As String() = {".jpg", ".jpeg", ".png", ".gif", ".pdf"} '定義允許的檔案格式
For i = 0 To allowedExtensions.Length - 1 '逐一檢查允許的格式中是否有上傳的格式
If fileExtension = allowedExtensions(i) Then
FileOk = True
End If
Next
If FileOk Then
Try
Me.FileUpload1.PostedFile.SaveAs(Path & fileName & ano & "." & nx) '將上傳的檔案儲存
Me.Label1.Text = "Upload Success!!" '傳回成功
cn.Open()
cmd.Parameters.Add("@url", System.Data.SqlDbType.VarChar).Value = "~/UpFile/" & fileName & ano & "." & nx
cmd.ExecuteNonQuery()
cn.Close()
Catch ex As Exception
Me.Label1.Text = "Upload False!!
" + ex.Message
End Try
Else
Me.Label1.Text = "檔案上傳失敗,請確認檔案格式是否正確!!"
End If
End If
FileUpload 限定副檔名
微軟官網
Protected Sub Page_Load(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack Then
Dim path As String = Server.MapPath("~/UploadedImages/")
Dim fileOK As Boolean = False
If FileUpload1.HasFile Then
Dim fileExtension As String
fileExtension = System.IO.Path. _
GetExtension(FileUpload1.FileName).ToLower()
Dim allowedExtensions As String() = _
{".jpg", ".jpeg", ".png", ".gif"}
For i As Integer = 0 To allowedExtensions.Length - 1
If fileExtension = allowedExtensions(i) Then
fileOK = True
End If
Next
If fileOK Then
Try
FileUpload1.PostedFile.SaveAs(path & _
FileUpload1.FileName)
Label1.Text = "File uploaded!"
Catch ex As Exception
Label1.Text = "File could not be uploaded."
End Try
Else
Label1.Text = "Cannot accept files of this type."
End If
End If
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack Then
Dim path As String = Server.MapPath("~/UploadedImages/")
Dim fileOK As Boolean = False
If FileUpload1.HasFile Then
Dim fileExtension As String
fileExtension = System.IO.Path. _
GetExtension(FileUpload1.FileName).ToLower()
Dim allowedExtensions As String() = _
{".jpg", ".jpeg", ".png", ".gif"}
For i As Integer = 0 To allowedExtensions.Length - 1
If fileExtension = allowedExtensions(i) Then
fileOK = True
End If
Next
If fileOK Then
Try
FileUpload1.PostedFile.SaveAs(path & _
FileUpload1.FileName)
Label1.Text = "File uploaded!"
Catch ex As Exception
Label1.Text = "File could not be uploaded."
End Try
Else
Label1.Text = "Cannot accept files of this type."
End If
End If
End If
End Sub
VB.Net2.0資料庫通用存取函式
原出處
編輯app.config,在【configuration】標籤內加入連線字串的設定如:
...
connectionString="Data Source=localhost;Initial Catalog=MyTestDB;Integrated Security=True"
providerName="System.Data.SqlClient" />
connectionString="Data Source=127.0.0.1;Initial Catalog=MyTestDB;User ID=sa;Password=1234"
providerName="System.Data.SqlClient" />
...
通用存取函式類別:
Imports System.Data.SqlClient
Imports System.Configuration
Public Class DBAccessFunc
'''
''' 從ConfigurationManager中的ConnectionStrings找出Initial Catalog
'''
''' ConnectionStrings名稱(String)
'''回傳資料庫名稱
'''從ConfigurationManager中的ConnectionStrings找出Initial Catalog
Public Shared Function getDBName(ByVal ConnName As String) As String
Dim val As String = ""
Dim ConnString As String = ConfigurationManager.ConnectionStrings(ConnName).ConnectionString
Dim i As Integer = ConnString.IndexOf("Initial Catalog=")
If i > -1 Then
val = ConnString.Substring(i + "Initial Catalog=".Length)
i = val.IndexOf(";")
If i > -1 Then
val = val.Substring(0, i)
End If
End If
Return val
End Function
Public Shared Function getConnString(ByVal ConnName As String) As String
Return ConfigurationManager.ConnectionStrings(ConnName).ConnectionString
End Function
Public Shared Function getConn(ByVal ConnName As String) As SqlConnection
Return New SqlConnection(getConnString(ConnName))
End Function
'''
''' 查詢資料庫
'''
''' 連線
''' 查詢內容
'''回傳查詢結果的DataTable
'''查詢資料庫並回傳查詢結果的DataTable
Public Shared Function getTable(ByRef cn As SqlConnection, ByRef sql As String, Optional ByVal isColseConn As Boolean = True) As Data.DataTable
Dim da As New SqlDataAdapter(sql, cn)
Dim dt As New Data.DataTable("dt_xml")
Try
If cn.State = ConnectionState.Closed Then cn.Open()
da.SelectCommand.CommandTimeout = 36000000
da.Fill(dt)
Catch ex As Exception
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
End Try
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Return dt
End Function
'''
''' 執行命令
'''
''' 連線
''' 查詢內容
'''回傳受影響的資料筆數
'''執行命令並回傳受影響的資料筆數
Public Shared Function doCmd(ByRef cn As SqlConnection, ByRef sql As String, Optional ByRef param() As SqlParameter = Nothing, Optional ByVal isColseConn As Boolean = True) As Integer
Dim result As Integer = 0
Dim cmd As New SqlCommand
Try
cmd.Connection = cn
cmd.CommandText = sql
If Not param Is Nothing Then
cmd.Parameters.AddRange(param)
End If
cmd.CommandTimeout = 36000000
If cn.State = ConnectionState.Closed Then cn.Open()
result = cmd.ExecuteNonQuery()
Catch ex As Exception
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
Finally
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
End Try
Return result
End Function
'''
''' 取得單一資料
'''
''' 連線
''' 查詢內容
'''回傳受影響的資料筆數
'''執行命令並回傳受影響的資料筆數
Public Shared Function doScalar(ByRef cn As SqlConnection, ByRef sql As String, Optional ByRef param() As SqlParameter = Nothing, Optional ByVal isColseConn As Boolean = True) As Object
Dim result As Object = Nothing
Dim cmd As New SqlCommand
Try
cmd.Connection = cn
cmd.CommandText = sql
If Not param Is Nothing Then
cmd.Parameters.AddRange(param)
End If
cmd.CommandTimeout = 36000000
If cn.State = ConnectionState.Closed Then cn.Open()
result = cmd.ExecuteScalar()
Catch ex As Exception
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
Finally
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
End Try
Return result
End Function
Public Function executeStoredProcedure(ByRef cn As SqlConnection, ByVal procedure As String, Optional ByRef param As SqlParameter() = Nothing, Optional ByRef output As SqlParameter() = Nothing, Optional ByVal isColseConn As Boolean = True) As Integer
Dim result As Integer = 0
Dim cmd As New SqlCommand(procedure, cn)
Try
cmd.CommandText = procedure
cmd.CommandTimeout = 36000000
cmd.CommandType = CommandType.StoredProcedure
If Not param Is Nothing Then cmd.Parameters.AddRange(param)
If Not output Is Nothing Then
For Each o As SqlParameter In output
o.Direction = ParameterDirection.Output
Next
cmd.Parameters.AddRange(output)
End If
'開啟資料庫連線
If cn.State = ConnectionState.Closed Then cn.Open()
'設定變數儲存受影響資料列
result = cmd.ExecuteNonQuery()
Catch ex As Exception
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
Finally
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
End Try
Return result
End Function
End Class
使用範例程式:
Dim connStr1 As String = DBGenFunc.getConnStr("MSSQLDB1")
Dim sourceTable As String() = {"[" & DBGenFunc.getDBName("MSSQLDB1") & "].[dbo].[" & "MyTestTab" & "]", _
"[" & DBGenFunc.getDBName("MSSQLDB1") & "].[dbo].[" & "MyContentTab" & "]"}
Dim param() As SqlClient.SqlParameter = {New SqlClient.SqlParameter("P0", SqlDbType.VarChar)}
Dim sql As String
Dim title As String
Console.WriteLine("doCmdScalar Start:")
sql = "SELECT Title" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf & _
" WHERE SN=@P0"
param(0).Value = 1
title = DBGenFunc.doCmdScalar(connStr1, sql, param)
Console.WriteLine("doCmdScalar" & vbTab & title)
Console.WriteLine("getTable Start:")
sql = "SELECT Title" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf
Dim dt As DataTable = DBGenFunc.getTable(connStr1, sql)
For Each r As DataRow In dt.Rows
title = r.Item(0)
Console.WriteLine("getTable" & vbTab & title)
Next
Console.WriteLine("getTableToArray Start:")
Dim data As String() = DBGenFunc.dataTableToArray(Of String)(dt, 0)
For Each r As String In data
title = r
Console.WriteLine("getTable" & vbTab & title)
Next
Console.WriteLine("doCmd Start:")
sql = "INSERT INTO " & sourceTable(0) & "" & vbCrLf & _
"VALUES(@P0,@P1)"
param = New SqlClient.SqlParameter() {New SqlClient.SqlParameter("P0", SqlDbType.VarChar), _
New SqlClient.SqlParameter("P1", SqlDbType.VarChar)}
param(0).Value = "TNew"
param(1).Value = "SNew"
title = DBGenFunc.doCmd(connStr1, sql, param)
Console.WriteLine("doCmd" & vbTab & title)
Console.WriteLine("getReader Start:")
sql = "SELECT Title, Subject" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf
Dim dr As SqlClient.SqlDataReader = DBGenFunc.getReader(connStr1, sql)
While dr.Read()
title = dr.Item(0)
Console.WriteLine("getReader" & vbTab & title & vbTab & dr.Item(1))
End While
DBGenFunc.closeReader()
執行結果:
doCmdScalar Start:
doCmdScalar T1
getTable Start:
getTable T1
getTable T2
getTable T3
getTable TNew
getTableToArray Start:
getTable T1
getTable T2
getTable T3
getTable TNew
doCmd Start:
doCmd 1
getReader Start:
getReader T1 S1
getReader T2 S2
getReader T3 S3
getReader TNew SNew
getReader TNew SNew
編輯app.config,在【configuration】標籤內加入連線字串的設定如:
...
providerName="System.Data.SqlClient" />
providerName="System.Data.SqlClient" />
...
通用存取函式類別:
Imports System.Data.SqlClient
Imports System.Configuration
Public Class DBAccessFunc
'''
''' 從ConfigurationManager中的ConnectionStrings找出Initial Catalog
'''
''' ConnectionStrings名稱(String)
'''
'''
Public Shared Function getDBName(ByVal ConnName As String) As String
Dim val As String = ""
Dim ConnString As String = ConfigurationManager.ConnectionStrings(ConnName).ConnectionString
Dim i As Integer = ConnString.IndexOf("Initial Catalog=")
If i > -1 Then
val = ConnString.Substring(i + "Initial Catalog=".Length)
i = val.IndexOf(";")
If i > -1 Then
val = val.Substring(0, i)
End If
End If
Return val
End Function
Public Shared Function getConnString(ByVal ConnName As String) As String
Return ConfigurationManager.ConnectionStrings(ConnName).ConnectionString
End Function
Public Shared Function getConn(ByVal ConnName As String) As SqlConnection
Return New SqlConnection(getConnString(ConnName))
End Function
'''
''' 查詢資料庫
'''
''' 連線
''' 查詢內容
'''
'''
Public Shared Function getTable(ByRef cn As SqlConnection, ByRef sql As String, Optional ByVal isColseConn As Boolean = True) As Data.DataTable
Dim da As New SqlDataAdapter(sql, cn)
Dim dt As New Data.DataTable("dt_xml")
Try
If cn.State = ConnectionState.Closed Then cn.Open()
da.SelectCommand.CommandTimeout = 36000000
da.Fill(dt)
Catch ex As Exception
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
End Try
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Return dt
End Function
'''
''' 執行命令
'''
''' 連線
''' 查詢內容
'''
'''
Public Shared Function doCmd(ByRef cn As SqlConnection, ByRef sql As String, Optional ByRef param() As SqlParameter = Nothing, Optional ByVal isColseConn As Boolean = True) As Integer
Dim result As Integer = 0
Dim cmd As New SqlCommand
Try
cmd.Connection = cn
cmd.CommandText = sql
If Not param Is Nothing Then
cmd.Parameters.AddRange(param)
End If
cmd.CommandTimeout = 36000000
If cn.State = ConnectionState.Closed Then cn.Open()
result = cmd.ExecuteNonQuery()
Catch ex As Exception
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
Finally
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
End Try
Return result
End Function
'''
''' 取得單一資料
'''
''' 連線
''' 查詢內容
'''
'''
Public Shared Function doScalar(ByRef cn As SqlConnection, ByRef sql As String, Optional ByRef param() As SqlParameter = Nothing, Optional ByVal isColseConn As Boolean = True) As Object
Dim result As Object = Nothing
Dim cmd As New SqlCommand
Try
cmd.Connection = cn
cmd.CommandText = sql
If Not param Is Nothing Then
cmd.Parameters.AddRange(param)
End If
cmd.CommandTimeout = 36000000
If cn.State = ConnectionState.Closed Then cn.Open()
result = cmd.ExecuteScalar()
Catch ex As Exception
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
Finally
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
End Try
Return result
End Function
Public Function executeStoredProcedure(ByRef cn As SqlConnection, ByVal procedure As String, Optional ByRef param As SqlParameter() = Nothing, Optional ByRef output As SqlParameter() = Nothing, Optional ByVal isColseConn As Boolean = True) As Integer
Dim result As Integer = 0
Dim cmd As New SqlCommand(procedure, cn)
Try
cmd.CommandText = procedure
cmd.CommandTimeout = 36000000
cmd.CommandType = CommandType.StoredProcedure
If Not param Is Nothing Then cmd.Parameters.AddRange(param)
If Not output Is Nothing Then
For Each o As SqlParameter In output
o.Direction = ParameterDirection.Output
Next
cmd.Parameters.AddRange(output)
End If
'開啟資料庫連線
If cn.State = ConnectionState.Closed Then cn.Open()
'設定變數儲存受影響資料列
result = cmd.ExecuteNonQuery()
Catch ex As Exception
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
Throw ex
Finally
cmd.Parameters.Clear()
If isColseConn And cn.State = ConnectionState.Open Then cn.Close()
End Try
Return result
End Function
End Class
使用範例程式:
Dim connStr1 As String = DBGenFunc.getConnStr("MSSQLDB1")
Dim sourceTable As String() = {"[" & DBGenFunc.getDBName("MSSQLDB1") & "].[dbo].[" & "MyTestTab" & "]", _
"[" & DBGenFunc.getDBName("MSSQLDB1") & "].[dbo].[" & "MyContentTab" & "]"}
Dim param() As SqlClient.SqlParameter = {New SqlClient.SqlParameter("P0", SqlDbType.VarChar)}
Dim sql As String
Dim title As String
Console.WriteLine("doCmdScalar Start:")
sql = "SELECT Title" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf & _
" WHERE SN=@P0"
param(0).Value = 1
title = DBGenFunc.doCmdScalar(connStr1, sql, param)
Console.WriteLine("doCmdScalar" & vbTab & title)
Console.WriteLine("getTable Start:")
sql = "SELECT Title" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf
Dim dt As DataTable = DBGenFunc.getTable(connStr1, sql)
For Each r As DataRow In dt.Rows
title = r.Item(0)
Console.WriteLine("getTable" & vbTab & title)
Next
Console.WriteLine("getTableToArray Start:")
Dim data As String() = DBGenFunc.dataTableToArray(Of String)(dt, 0)
For Each r As String In data
title = r
Console.WriteLine("getTable" & vbTab & title)
Next
Console.WriteLine("doCmd Start:")
sql = "INSERT INTO " & sourceTable(0) & "" & vbCrLf & _
"VALUES(@P0,@P1)"
param = New SqlClient.SqlParameter() {New SqlClient.SqlParameter("P0", SqlDbType.VarChar), _
New SqlClient.SqlParameter("P1", SqlDbType.VarChar)}
param(0).Value = "TNew"
param(1).Value = "SNew"
title = DBGenFunc.doCmd(connStr1, sql, param)
Console.WriteLine("doCmd" & vbTab & title)
Console.WriteLine("getReader Start:")
sql = "SELECT Title, Subject" & vbCrLf & _
" FROM " & sourceTable(0) & "" & vbCrLf
Dim dr As SqlClient.SqlDataReader = DBGenFunc.getReader(connStr1, sql)
While dr.Read()
title = dr.Item(0)
Console.WriteLine("getReader" & vbTab & title & vbTab & dr.Item(1))
End While
DBGenFunc.closeReader()
執行結果:
doCmdScalar Start:
doCmdScalar T1
getTable Start:
getTable T1
getTable T2
getTable T3
getTable TNew
getTableToArray Start:
getTable T1
getTable T2
getTable T3
getTable TNew
doCmd Start:
doCmd 1
getReader Start:
getReader T1 S1
getReader T2 S2
getReader T3 S3
getReader TNew SNew
getReader TNew SNew
asp.net 中的 主从 新增,修改,删除
在asp.net中關於主從新增問題,網絡上很多朋友問起,很多解決的辦法不是很好,關鍵是同步問題,下面是我的做法,
歡迎大家提出更好的辦法。
在主從新增中,主表一筆,從表多筆,在新增,,修改,刪除從表時必須和主表一起保存,並且主表和從表都會有新增,修改,刪除。所以必須用到以下技術:
1.首先必須用到事務來確保一致性。
2.需要用到ado.net的批量更新。
3.從表數據必須在內存中處理,然後在批量更新到數據庫中
下面是部分代碼
private DataSet ds
{
get
{
object o = ViewState["ds"];
return o == null ? null : (DataSet)o;
}
set { ViewState["ds"] = value; }
}
定義一個dataset屬性,用來在內存中操作從表數據,也可以保存在Session中
public bool SaveData(Model.Budget_Mdl mdl, DataSet ds, string tableName, string EditMethod, out string ret)
{
//保存主表
SqlConnection conn = new SqlConnection(SQLHelper.strCONN);
lock (this)
{
conn.Open();
SqlCommand cmd = new SqlCommand();
SqlTransaction tran;
tran = conn.BeginTransaction();
cmd.Connection = conn;
cmd.Transaction = tran;
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SPC_Bud";
cmd.Parameters.Add("@EditMethod", SqlDbType.NChar).Value = EditMethod;
cmd.Parameters.Add("@CHANFORM_ID", SqlDbType.NChar).Value = mdl.CHANFORM_ID;
cmd.Parameters.Add("@Bill_Character", SqlDbType.NChar).Value = mdl.Bill_Character;
cmd.Parameters.Add("@BUD_YEAR", SqlDbType.Int).Value = mdl.BUD_YEAR;
cmd.Parameters.Add("@APPLICANT", SqlDbType.NVarChar).Value = mdl.APPLICANT;
cmd.Parameters.Add("@APPLYDATE", SqlDbType.NChar).Value = mdl.APPLYDATE.ToString("yyyy-MM-dd");
cmd.Parameters.Add("@FORMTYPE", SqlDbType.NChar).Value = mdl.FORMTYPE;
cmd.Parameters.Add("@REMARKS", SqlDbType.NVarChar).Value = mdl.REMARKS;
cmd.Parameters.Add("@C_USER", SqlDbType.NVarChar).Value = mdl.C_USER;
cmd.Parameters.Add("@M_USER", SqlDbType.NVarChar).Value = mdl.M_USER;
cmd.Parameters.Add("@ret", SqlDbType.NVarChar);
cmd.Parameters["@ret"].Size = 10;
cmd.Parameters["@ret"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
ret = Convert.ToString(cmd.Parameters["@ret"].Value);
foreach (DataRow row in ds.Tables["budDtl"].Rows)
{
if (row.RowState == DataRowState.Added)
row["CHANFORM_ID"] = ret;
}
//保存細表
if (EditMethod == "I" || EditMethod == "U")
{
string strSql = "Select * from TB_BUDGET_DETAIL";
Helper.BatchUpdate(ds, conn, tableName, strSql, tran);
}
tran.Commit();
return true;
}
catch (Exception err)
{
tran.Rollback();
throw err;
}
finally
{
conn.Close();
}
}
}
Model用來傳遞主表,DataSet用來傳遞從表
要注意的地方是從表必須有主鍵
歡迎大家提出更好的辦法。
在主從新增中,主表一筆,從表多筆,在新增,,修改,刪除從表時必須和主表一起保存,並且主表和從表都會有新增,修改,刪除。所以必須用到以下技術:
1.首先必須用到事務來確保一致性。
2.需要用到ado.net的批量更新。
3.從表數據必須在內存中處理,然後在批量更新到數據庫中
下面是部分代碼
private DataSet ds
{
get
{
object o = ViewState["ds"];
return o == null ? null : (DataSet)o;
}
set { ViewState["ds"] = value; }
}
定義一個dataset屬性,用來在內存中操作從表數據,也可以保存在Session中
public bool SaveData(Model.Budget_Mdl mdl, DataSet ds, string tableName, string EditMethod, out string ret)
{
//保存主表
SqlConnection conn = new SqlConnection(SQLHelper.strCONN);
lock (this)
{
conn.Open();
SqlCommand cmd = new SqlCommand();
SqlTransaction tran;
tran = conn.BeginTransaction();
cmd.Connection = conn;
cmd.Transaction = tran;
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SPC_Bud";
cmd.Parameters.Add("@EditMethod", SqlDbType.NChar).Value = EditMethod;
cmd.Parameters.Add("@CHANFORM_ID", SqlDbType.NChar).Value = mdl.CHANFORM_ID;
cmd.Parameters.Add("@Bill_Character", SqlDbType.NChar).Value = mdl.Bill_Character;
cmd.Parameters.Add("@BUD_YEAR", SqlDbType.Int).Value = mdl.BUD_YEAR;
cmd.Parameters.Add("@APPLICANT", SqlDbType.NVarChar).Value = mdl.APPLICANT;
cmd.Parameters.Add("@APPLYDATE", SqlDbType.NChar).Value = mdl.APPLYDATE.ToString("yyyy-MM-dd");
cmd.Parameters.Add("@FORMTYPE", SqlDbType.NChar).Value = mdl.FORMTYPE;
cmd.Parameters.Add("@REMARKS", SqlDbType.NVarChar).Value = mdl.REMARKS;
cmd.Parameters.Add("@C_USER", SqlDbType.NVarChar).Value = mdl.C_USER;
cmd.Parameters.Add("@M_USER", SqlDbType.NVarChar).Value = mdl.M_USER;
cmd.Parameters.Add("@ret", SqlDbType.NVarChar);
cmd.Parameters["@ret"].Size = 10;
cmd.Parameters["@ret"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
ret = Convert.ToString(cmd.Parameters["@ret"].Value);
foreach (DataRow row in ds.Tables["budDtl"].Rows)
{
if (row.RowState == DataRowState.Added)
row["CHANFORM_ID"] = ret;
}
//保存細表
if (EditMethod == "I" || EditMethod == "U")
{
string strSql = "Select * from TB_BUDGET_DETAIL";
Helper.BatchUpdate(ds, conn, tableName, strSql, tran);
}
tran.Commit();
return true;
}
catch (Exception err)
{
tran.Rollback();
throw err;
}
finally
{
conn.Close();
}
}
}
Model用來傳遞主表,DataSet用來傳遞從表
要注意的地方是從表必須有主鍵
Parameter Queries in ASP.NET with MS Access
原出處
Good!!
------------
A selection of code samples for executing queries against MS Access using parameters.
Making use of the ASP.NET 2.0 datasource controls is fine, but it is important to understand how to manually create data access code. Best practice dictates that, at the very least, parameters are used to represent values that are passed into the SQL to be executed, rather than un-sanitised values straight from the user. The main reason for this cannot be over-emphasised in terms of its importance - it protects the application against SQL Injection attacks. In addition, parameters do not require delimiters. Therefore there is no need to worry about octothorpes (#) or apostrophes for dates, or doubling single quotes in strings.
These samples all assume that the values being passed into the parameters have been properly validated for datatype, existence, range etc, according to the business rules for the application. The serverside validation code is not included, as it will differ from app to app, and is not the focus of these samples anyway. However, it is important to stress that all user input must be validated server-side before being included in a SQL statement. Better to reject it outright, rather than have to unpick rubbish that pollutes the database...
The required components are an OleDbConnection object, a ConnectionString property, an OleDbCommand object and an OleDbParameterCollection. These all reside in the System.Data.OleDb namespace, which needs to be referenced. Also, the connection string is held in the Web.Config, and a static method GetConnString() has been created in a class called Utils (also static) to retrieve it:
[C#]
public static string GetConnString()
{
return WebConfigurationManager.ConnectionStrings["myConnStr"].ConnectionString;
}
[VB]
Public Shared Function GetConnString() As String
Return WebConfigurationManager.ConnectionStrings("myConnStr").ConnectionString
End Function
For simplicity, you can replace Utils.GetConnString with a valid Access connection string such as:
"Microsoft.Jet.OleDb.4.0;Data Source=|DataDirectory|Northwind.mdb"
To make use of |DataDirectory| make sure that your database file is in the App_Data folder of your web site.
OleDb Parameters are recognised by their position, not by their name. Consequently, it is vital to ensure that parameters are added to the collection in the order they appear in the SQL, otherwise a "Too few parameters..." exception could occur. At the very least, your values will get inserted into the wrong fields, or nothing happens at all. For the sake of code readability, AddWithValues(string, object) can take a non-empty string giving a name to the parameter, although an empty string ("") will do.
One final note about parameter markers: in the samples below, the markers are represented by question marks ( ? ). Access (or the Jet provider) is also happy to work with SQL Server-style parameter markers that are prefixed with @, so the first example CommandText can be replaced with:
"Insert Into Contacts (FirstName, LastName) Values (@FirstName, @LastName)"
INSERT
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Insert Into Contacts (FirstName, LastName) Values (?,?)";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Insert Into Contacts (FirstName, LastName) Values (?,?)"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
UPDATE
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Update Contacts Set FirstName = ?, LastName = ?";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Update Contacts Set FirstName = ?, LastName = ?"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
DELETE
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Delete * From Contacts Where FirstName = ? And LastName = ?";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Delete * From Contacts Where FirstName = ? And LastName = ?"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
SELECT
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Select * From Contacts Where FirstName = ? And LastName = ?";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Response.Write(reader["FirstName"].ToString() + " " + reader["LastName"].ToString());
}
}
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Select * From Contacts Where FirstName = ? And LastName = ?"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
Using reader As OleDbDataReader = cmd.ExecuteReader()
While reader.Read()
Response.Write(reader("FirstName").ToString() + " " + reader("LastName").ToString())
End While
End Using
End Using
End Using
Saved Queries
The code samples above will work equally well with minimal changes for Saved Queries in MS Access. The CommandType will need to be changed to "StoredProcedure", and the name of the query needs to be passed as a string in place of the SQL statement. As an example, if a Saved Query was created in Access called AddContact, this is how the INSERT example would alter:
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "AddContact";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "AddContact"
Using Conn As New OleDbConnection(ConnString)
Using Cmd As New OleDbCommand(SqlString, Conn)
Cmd.CommandType = CommandType.StoredProcedure
Cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
Cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
Conn.Open()
Cmd.ExecuteNonQuery()
End Using
End Using
You may end up using a legacy Access database, which has embedded spaces in the names of the queries. I know - only an idiot does this sort of thing. Well, the download version of Northwind.mdb (from Microsoft) has embedded spaces in object names... Anyway, the way to get round this is to surround the query name with [ ] brackets:
string query = "[Current Product List]";
Good!!
------------
A selection of code samples for executing queries against MS Access using parameters.
Making use of the ASP.NET 2.0 datasource controls is fine, but it is important to understand how to manually create data access code. Best practice dictates that, at the very least, parameters are used to represent values that are passed into the SQL to be executed, rather than un-sanitised values straight from the user. The main reason for this cannot be over-emphasised in terms of its importance - it protects the application against SQL Injection attacks. In addition, parameters do not require delimiters. Therefore there is no need to worry about octothorpes (#) or apostrophes for dates, or doubling single quotes in strings.
These samples all assume that the values being passed into the parameters have been properly validated for datatype, existence, range etc, according to the business rules for the application. The serverside validation code is not included, as it will differ from app to app, and is not the focus of these samples anyway. However, it is important to stress that all user input must be validated server-side before being included in a SQL statement. Better to reject it outright, rather than have to unpick rubbish that pollutes the database...
The required components are an OleDbConnection object, a ConnectionString property, an OleDbCommand object and an OleDbParameterCollection. These all reside in the System.Data.OleDb namespace, which needs to be referenced. Also, the connection string is held in the Web.Config, and a static method GetConnString() has been created in a class called Utils (also static) to retrieve it:
[C#]
public static string GetConnString()
{
return WebConfigurationManager.ConnectionStrings["myConnStr"].ConnectionString;
}
[VB]
Public Shared Function GetConnString() As String
Return WebConfigurationManager.ConnectionStrings("myConnStr").ConnectionString
End Function
For simplicity, you can replace Utils.GetConnString with a valid Access connection string such as:
"Microsoft.Jet.OleDb.4.0;Data Source=|DataDirectory|Northwind.mdb"
To make use of |DataDirectory| make sure that your database file is in the App_Data folder of your web site.
OleDb Parameters are recognised by their position, not by their name. Consequently, it is vital to ensure that parameters are added to the collection in the order they appear in the SQL, otherwise a "Too few parameters..." exception could occur. At the very least, your values will get inserted into the wrong fields, or nothing happens at all. For the sake of code readability, AddWithValues(string, object) can take a non-empty string giving a name to the parameter, although an empty string ("") will do.
One final note about parameter markers: in the samples below, the markers are represented by question marks ( ? ). Access (or the Jet provider) is also happy to work with SQL Server-style parameter markers that are prefixed with @, so the first example CommandText can be replaced with:
"Insert Into Contacts (FirstName, LastName) Values (@FirstName, @LastName)"
INSERT
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Insert Into Contacts (FirstName, LastName) Values (?,?)";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Insert Into Contacts (FirstName, LastName) Values (?,?)"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
UPDATE
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Update Contacts Set FirstName = ?, LastName = ?";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Update Contacts Set FirstName = ?, LastName = ?"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
DELETE
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Delete * From Contacts Where FirstName = ? And LastName = ?";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Delete * From Contacts Where FirstName = ? And LastName = ?"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
SELECT
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "Select * From Contacts Where FirstName = ? And LastName = ?";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
using (OleDbDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Response.Write(reader["FirstName"].ToString() + " " + reader["LastName"].ToString());
}
}
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "Select * From Contacts Where FirstName = ? And LastName = ?"
Using conn As New OleDbConnection(ConnString)
Using cmd As New OleDbCommand(SqlString, conn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
conn.Open()
Using reader As OleDbDataReader = cmd.ExecuteReader()
While reader.Read()
Response.Write(reader("FirstName").ToString() + " " + reader("LastName").ToString())
End While
End Using
End Using
End Using
Saved Queries
The code samples above will work equally well with minimal changes for Saved Queries in MS Access. The CommandType will need to be changed to "StoredProcedure", and the name of the query needs to be passed as a string in place of the SQL statement. As an example, if a Saved Query was created in Access called AddContact, this is how the INSERT example would alter:
[C#]
string ConnString = Utils.GetConnString();
string SqlString = "AddContact";
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cmd = new OleDbCommand(SqlString, conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text);
cmd.Parameters.AddWithValue("LastName", txtLastName.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
[VB]
Dim ConnString As String = Utils.GetConnString()
Dim SqlString As String = "AddContact"
Using Conn As New OleDbConnection(ConnString)
Using Cmd As New OleDbCommand(SqlString, Conn)
Cmd.CommandType = CommandType.StoredProcedure
Cmd.Parameters.AddWithValue("FirstName", txtFirstName.Text)
Cmd.Parameters.AddWithValue("LastName", txtLastName.Text)
Conn.Open()
Cmd.ExecuteNonQuery()
End Using
End Using
You may end up using a legacy Access database, which has embedded spaces in the names of the queries. I know - only an idiot does this sort of thing. Well, the download version of Northwind.mdb (from Microsoft) has embedded spaces in object names... Anyway, the way to get round this is to surround the query name with [ ] brackets:
string query = "[Current Product List]";
2010年9月23日 星期四
2010年9月22日 星期三
SQL Server 資料庫維護
本文件針對SQL Server 2005上的SmartIT資料庫作效能改進,與資料庫整理時可參考使用。
介紹說明:
一、DB Backup 「單一備份」
二、DB Backup 「每日備份至一週」
三、DB reindex 「資料庫索引重建」
四、資料庫壓縮
五、資料庫修復
六、快速查詢資料庫資料表筆數
七、清除交易紀錄檔
八、操作流程建議
九、排程設定圖解
註:文中所有之DB_Name,意指SmartIT之資料庫名稱,標記紅色字體為可變更。
一、DB Backup 「單一備份」
-----------------------------------------DB Backup-----------------------------------------------
BACKUP DATABASE [DB_Name]
TO DISK = N'D:\SmartIT_DB_BAK\smartit_bk.bak' WITH INIT,NOUNLOAD,
NAME = N'smartit_bk',NOSKIP,STATS = 10,NOFORMAT
----------------------------------------- DB Backup-----------------------------------------------
*DB_Name,意指SmartIT資料庫名稱
*D:\SmartIT_DB_BAK\smartit_bk.bak,意指備份路徑及備份檔案名稱
建議設定方式:
資料庫備份建議為一周一次,如果資料異動不多,
可設定一個月一次,在週六或週日執行比較不影響效能。
==========================================================
二、DB Backup 「每日備份至一週」
說明:
使用下列指令可以備份資料庫,只備份七個檔案不會累加,檔名為週一到週日,
會做完整備份。
-------------------------- DB Backup 週備份-----------------------------
DECLARE @bkFileName nvarchar(255)
SET DATEFIRST 1
SELECT @bkFileName =
CASE DATEPART(dw, GETDATE())
WHEN 1 THEN N'D:\星期一.bak'
WHEN 2 THEN N'D:\星期二.bak'
WHEN 3 THEN N'D:\星期三.bak'
WHEN 4 THEN N'D:\星期四.bak'
WHEN 5 THEN N'D:\星期五.bak'
WHEN 6 THEN N'D:\星期六.bak'
WHEN 7 THEN N'D:\星期日.bak'
END
BACKUP DATABASE [DB_Name] TO DISK = @bkFileName WITH INIT,NOUNLOAD,NAME=N'SMARTIT 備份',NOSKIP,STATS=10,NOFORMAT
-------------------------- DB Backup 週備份-----------------------------
*DB_Name,意指SmartIT資料庫名稱
*D:\星期一.bak,意指備份路徑及備份檔案
建議操作設定方式:
使用此備份可設定每天都做備份,但是每次備份為full Backup,且不是累加方式備份,
只會產生7個檔案,週一到週日,如果硬碟夠大的話可以用來做這樣的備份。
==========================================================
三、DB reindex 「資料庫索引重建」
說明:
重建索引的目的在於:當使用者需透過該欄位,
從資料檔(或表格)搜尋所要的記錄(或行)時,借索引之助,可大幅提高資料檢索的速度。
------------------------ DBREINDEX ALL TABLE -----------------------------
DECLARE @TableName nvarchar(261)
DECLARE @SQLStatement nvarchar(4000)
DECLARE TableList CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT
QUOTENAME(TABLE_SCHEMA) +
N'.' +
QUOTENAME(TABLE_NAME)
FROM
INFORMATION_SCHEMA.TABLES
WHERE EXISTS
(
SELECT *
FROM sysindexes
WHERE id =
OBJECT_ID(QUOTENAME(TABLE_SCHEMA) +
N'.' +
QUOTENAME(TABLE_NAME)) AND
indid IN(0,1)
)
OPEN TableList
WHILE 1 = 1
BEGIN
FETCH NEXT FROM TableList INTO @TableName
IF @@FETCH_STATUS = -1 BREAK
RAISERROR ('Reindexing %s', 0, 1, @TableName) WITH NOWAIT
Print(@TableName)
DBCC DBREINDEX (@TableName, '', 70)
EXEC(@SQLStatement)
END
CLOSE TableList
DEALLOCATE TableList
------------------------ DBREINDEX ALL TABLE --------------------------
建議操作設定方式:
此設定建議在清除交易紀錄檔之前執行,
於每天晚上22:00執行,因執行後會有交易紀錄。
==========================================================
四、資料庫壓縮
說明:
執行此設定會縮減 User DB 使用者資料庫的檔案大小,
讓User DB 的檔案騰出 10% 的可用空間。
--------------------------資料庫壓縮--------------------------
DBCC SHRINKDATABASE (DB_Name, 10)
--------------------------資料庫壓縮--------------------------
*DB_Name,意指SmartIT資料庫名稱
建議操作設定方式:
資料庫壓縮可設定手動執行,如有清除資料後再作此壓縮比較適合。
==========================================================
五、資料庫修復
說明:
使用此script的時機,主要在於當我們在使用報表時,
在擷取資料時如果出現『逾時過期』訊息時,建議使用下列指令修復資料庫,
特別注意第一行與最後一行『sp_dboption DB_Name,single, true』
『sp_dboption DB_Name,single, false』與中間指令要分開執行。
Step1:
----------------------------------------------------
sp_dboption DB_Name, single , true
----------------------------------------------------
**DB_Name,意指SmartIT資料庫名稱
**如執行時發生失敗,請重新啟動SQL Server Service後,再試一次
Step2:
----------------------------------------------------
dbcc checktable ("Table_Name",repair_allow_data_loss)
dbcc dbreindex ("Table_Name")
----------------------------------------------------
**Table_Name,意指SmartIT資料表名稱
Step3:
----------------------------------------------------
sp_dboption DB_Name, single , false
----------------------------------------------------
**DB_Name,意指SmartIT資料庫名稱
下列為可能需要修復的資料表對照表:
Table Name / 資料名稱
organization_group 組織
users 人員
smartit SmartIT主表(電腦清單)
software 軟體
virtual_software 軟體虛擬群組
virtual_software_mapping 虛擬群組對應
software_change 軟體變更
system_change 系統變更
appusage 軟體使用率
url_audit 網站稽核
print_log 印表機稽核
imlog 即時通訊稽核
files_audit_log 檔案抄寫稽核
**此段設定可針對有問題部分執行即可,不需全部執行。
建議操作設定方式:
資料庫修復使用時機適合在某資料表過大造成報表無法產生時執行,
執行時會將資料庫離線,建議在非資產回傳尖峰時間執行,
且須停止SmartIT Server服務,以加快執行速度。
==========================================================
六、快速查詢資料庫資料表筆數
說明:
使用下列指令可以快速查詢資料表的大小,
藉此方式可以判斷是否有哪些資料表資料量過大,提供維護人員或管理人員參考使用。
-----------------------快速查詢資料庫資料表筆數-------------------------
select a.name,max(b.rows) as rows
from sysobjects a,sysindexes b where a.id= b.id and a.xtype = 'U'
group by a.name
order by max(b.rows)
-----------------------快速查詢資料庫資料表筆數-------------------------
建議操作設定方式:
使用此Script可搭配資料庫修復使用,目的在於先檢測資料庫每個資料表的資料量,
藉此判斷是否需要做資料庫修復。
==========================================================
七、清除交易紀錄檔
說明:
交易紀錄檔的產生,是每個與資料庫連結的動作之紀錄,
若SQL Server的交易紀錄一直沒有去清除的話,會導致整個資料庫都不能使用。
指令說明:
執行Backup Log with Truncate_Only 其用法是備份資料庫的Log檔,
由於我們在語法中沒有指定備份的裝置為何,
Sql Server即會認為此動作為單純要把已交易完成的Log資料清空
(已交易完成的資料所指即為已commit的資料),
而Truncate_Only的選項則是告訴Sql Server目的在清空Log之空間,
至於清出的空間則由Sql Server管理,不還給OS。
Backup Log完成後,要再執行DBCC SHRINKFILE ,其作為為將資料的空間作重整及壓縮至2M。
----------------------------清除交易紀錄檔--------------------------
use DB_Name
Backup Log DB_Name with TRUNCATE_ONLY
dbcc shrinkfile (DB_Name _log , 2)
----------------------------清除交易紀錄檔--------------------------
*DB_Name,意指SmartIT資料庫名稱
--------清除DB Name為SmartIT的交易紀錄檔範例--------
use SmartIT
Backup Log SmartIT with TRUNCATE_ONLY
dbcc shrinkfile (SmartIT_log , 2)
--------清除DB Name為SmartIT的交易紀錄檔範例--------
建議操作設定方式:
建議交易紀錄檔可設定每天晚上23:30執行,交易紀錄檔越大,存取資料的速度也會越慢。
==========================================================
八、操作流程建議:
Mdf 過大,資料量過多
順序為
1、資料表查詢 <確認資料表資料大小>
2、詢問user是否可以先進行瘦身(記錄檔維護)
3、清除交易紀錄檔
4、壓縮資料庫
5、db reindex
6、備份
Ldf 過大,交易紀錄檔太大
順序為
1、清除交易紀錄檔
2、資料表查詢
3、詢問user是否可以先進行瘦身(記錄檔維護)
4、清除交易紀錄檔
5、壓縮
6、db reindex
7、備份
==========================================================
介紹說明:
一、DB Backup 「單一備份」
二、DB Backup 「每日備份至一週」
三、DB reindex 「資料庫索引重建」
四、資料庫壓縮
五、資料庫修復
六、快速查詢資料庫資料表筆數
七、清除交易紀錄檔
八、操作流程建議
九、排程設定圖解
註:文中所有之DB_Name,意指SmartIT之資料庫名稱,標記紅色字體為可變更。
一、DB Backup 「單一備份」
-----------------------------------------DB Backup-----------------------------------------------
BACKUP DATABASE [DB_Name]
TO DISK = N'D:\SmartIT_DB_BAK\smartit_bk.bak' WITH INIT,NOUNLOAD,
NAME = N'smartit_bk',NOSKIP,STATS = 10,NOFORMAT
----------------------------------------- DB Backup-----------------------------------------------
*DB_Name,意指SmartIT資料庫名稱
*D:\SmartIT_DB_BAK\smartit_bk.bak,意指備份路徑及備份檔案名稱
建議設定方式:
資料庫備份建議為一周一次,如果資料異動不多,
可設定一個月一次,在週六或週日執行比較不影響效能。
==========================================================
二、DB Backup 「每日備份至一週」
說明:
使用下列指令可以備份資料庫,只備份七個檔案不會累加,檔名為週一到週日,
會做完整備份。
-------------------------- DB Backup 週備份-----------------------------
DECLARE @bkFileName nvarchar(255)
SET DATEFIRST 1
SELECT @bkFileName =
CASE DATEPART(dw, GETDATE())
WHEN 1 THEN N'D:\星期一.bak'
WHEN 2 THEN N'D:\星期二.bak'
WHEN 3 THEN N'D:\星期三.bak'
WHEN 4 THEN N'D:\星期四.bak'
WHEN 5 THEN N'D:\星期五.bak'
WHEN 6 THEN N'D:\星期六.bak'
WHEN 7 THEN N'D:\星期日.bak'
END
BACKUP DATABASE [DB_Name] TO DISK = @bkFileName WITH INIT,NOUNLOAD,NAME=N'SMARTIT 備份',NOSKIP,STATS=10,NOFORMAT
-------------------------- DB Backup 週備份-----------------------------
*DB_Name,意指SmartIT資料庫名稱
*D:\星期一.bak,意指備份路徑及備份檔案
建議操作設定方式:
使用此備份可設定每天都做備份,但是每次備份為full Backup,且不是累加方式備份,
只會產生7個檔案,週一到週日,如果硬碟夠大的話可以用來做這樣的備份。
==========================================================
三、DB reindex 「資料庫索引重建」
說明:
重建索引的目的在於:當使用者需透過該欄位,
從資料檔(或表格)搜尋所要的記錄(或行)時,借索引之助,可大幅提高資料檢索的速度。
------------------------ DBREINDEX ALL TABLE -----------------------------
DECLARE @TableName nvarchar(261)
DECLARE @SQLStatement nvarchar(4000)
DECLARE TableList CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT
QUOTENAME(TABLE_SCHEMA) +
N'.' +
QUOTENAME(TABLE_NAME)
FROM
INFORMATION_SCHEMA.TABLES
WHERE EXISTS
(
SELECT *
FROM sysindexes
WHERE id =
OBJECT_ID(QUOTENAME(TABLE_SCHEMA) +
N'.' +
QUOTENAME(TABLE_NAME)) AND
indid IN(0,1)
)
OPEN TableList
WHILE 1 = 1
BEGIN
FETCH NEXT FROM TableList INTO @TableName
IF @@FETCH_STATUS = -1 BREAK
RAISERROR ('Reindexing %s', 0, 1, @TableName) WITH NOWAIT
Print(@TableName)
DBCC DBREINDEX (@TableName, '', 70)
EXEC(@SQLStatement)
END
CLOSE TableList
DEALLOCATE TableList
------------------------ DBREINDEX ALL TABLE --------------------------
建議操作設定方式:
此設定建議在清除交易紀錄檔之前執行,
於每天晚上22:00執行,因執行後會有交易紀錄。
==========================================================
四、資料庫壓縮
說明:
執行此設定會縮減 User DB 使用者資料庫的檔案大小,
讓User DB 的檔案騰出 10% 的可用空間。
--------------------------資料庫壓縮--------------------------
DBCC SHRINKDATABASE (DB_Name, 10)
--------------------------資料庫壓縮--------------------------
*DB_Name,意指SmartIT資料庫名稱
建議操作設定方式:
資料庫壓縮可設定手動執行,如有清除資料後再作此壓縮比較適合。
==========================================================
五、資料庫修復
說明:
使用此script的時機,主要在於當我們在使用報表時,
在擷取資料時如果出現『逾時過期』訊息時,建議使用下列指令修復資料庫,
特別注意第一行與最後一行『sp_dboption DB_Name,single, true』
『sp_dboption DB_Name,single, false』與中間指令要分開執行。
Step1:
----------------------------------------------------
sp_dboption DB_Name, single , true
----------------------------------------------------
**DB_Name,意指SmartIT資料庫名稱
**如執行時發生失敗,請重新啟動SQL Server Service後,再試一次
Step2:
----------------------------------------------------
dbcc checktable ("Table_Name",repair_allow_data_loss)
dbcc dbreindex ("Table_Name")
----------------------------------------------------
**Table_Name,意指SmartIT資料表名稱
Step3:
----------------------------------------------------
sp_dboption DB_Name, single , false
----------------------------------------------------
**DB_Name,意指SmartIT資料庫名稱
下列為可能需要修復的資料表對照表:
Table Name / 資料名稱
organization_group 組織
users 人員
smartit SmartIT主表(電腦清單)
software 軟體
virtual_software 軟體虛擬群組
virtual_software_mapping 虛擬群組對應
software_change 軟體變更
system_change 系統變更
appusage 軟體使用率
url_audit 網站稽核
print_log 印表機稽核
imlog 即時通訊稽核
files_audit_log 檔案抄寫稽核
**此段設定可針對有問題部分執行即可,不需全部執行。
建議操作設定方式:
資料庫修復使用時機適合在某資料表過大造成報表無法產生時執行,
執行時會將資料庫離線,建議在非資產回傳尖峰時間執行,
且須停止SmartIT Server服務,以加快執行速度。
==========================================================
六、快速查詢資料庫資料表筆數
說明:
使用下列指令可以快速查詢資料表的大小,
藉此方式可以判斷是否有哪些資料表資料量過大,提供維護人員或管理人員參考使用。
-----------------------快速查詢資料庫資料表筆數-------------------------
select a.name,max(b.rows) as rows
from sysobjects a,sysindexes b where a.id= b.id and a.xtype = 'U'
group by a.name
order by max(b.rows)
-----------------------快速查詢資料庫資料表筆數-------------------------
建議操作設定方式:
使用此Script可搭配資料庫修復使用,目的在於先檢測資料庫每個資料表的資料量,
藉此判斷是否需要做資料庫修復。
==========================================================
七、清除交易紀錄檔
說明:
交易紀錄檔的產生,是每個與資料庫連結的動作之紀錄,
若SQL Server的交易紀錄一直沒有去清除的話,會導致整個資料庫都不能使用。
指令說明:
執行Backup Log with Truncate_Only 其用法是備份資料庫的Log檔,
由於我們在語法中沒有指定備份的裝置為何,
Sql Server即會認為此動作為單純要把已交易完成的Log資料清空
(已交易完成的資料所指即為已commit的資料),
而Truncate_Only的選項則是告訴Sql Server目的在清空Log之空間,
至於清出的空間則由Sql Server管理,不還給OS。
Backup Log完成後,要再執行DBCC SHRINKFILE ,其作為為將資料的空間作重整及壓縮至2M。
----------------------------清除交易紀錄檔--------------------------
use DB_Name
Backup Log DB_Name with TRUNCATE_ONLY
dbcc shrinkfile (DB_Name _log , 2)
----------------------------清除交易紀錄檔--------------------------
*DB_Name,意指SmartIT資料庫名稱
--------清除DB Name為SmartIT的交易紀錄檔範例--------
use SmartIT
Backup Log SmartIT with TRUNCATE_ONLY
dbcc shrinkfile (SmartIT_log , 2)
--------清除DB Name為SmartIT的交易紀錄檔範例--------
建議操作設定方式:
建議交易紀錄檔可設定每天晚上23:30執行,交易紀錄檔越大,存取資料的速度也會越慢。
==========================================================
八、操作流程建議:
Mdf 過大,資料量過多
順序為
1、資料表查詢 <確認資料表資料大小>
2、詢問user是否可以先進行瘦身(記錄檔維護)
3、清除交易紀錄檔
4、壓縮資料庫
5、db reindex
6、備份
Ldf 過大,交易紀錄檔太大
順序為
1、清除交易紀錄檔
2、資料表查詢
3、詢問user是否可以先進行瘦身(記錄檔維護)
4、清除交易紀錄檔
5、壓縮
6、db reindex
7、備份
==========================================================
刪不掉資料表裡的資料的解決方法之三種比較DELETE,TRUNCATE,DROP
有時用SQL Server 2005的Management Studio或用VisualStudio開啟資料庫裡面的
資料表後,想一次把裡面幾千筆資料全部刪掉時,就會整個當住當在那邊不能刪
所以可以改成用查詢指令來刪
指令有三種DELETE ,TRUNCATE ,DROP
1.
DELETE是DML指令,可以配合WHERE來刪除特定的資料列
DELETE後的資料可以用COMMIT確認刪除或是用ROLLBACK回復刪除的資料
語法是:
DELETE FROM 資料表 WHERE 某欄位='ABC'
2.
TRUNCATE是DDL指令,用了之後刪掉的資料不能回復,速度很快比DELETE還快,但是只能一次刪掉全部的資料表內容而不行指定要刪哪一列
語法是:
USE 資料庫的名字
TRUNCATE table 資料表的名字
就可以把資料表裡的內容都快速清空
3.
DROP是DDL指令,用了之後刪掉的資料不能回復,直接把資料表整個刪了,注意是連資料表都不見了喔
語法是:
DROP TABLE 資料表的名字
資料表後,想一次把裡面幾千筆資料全部刪掉時,就會整個當住當在那邊不能刪
所以可以改成用查詢指令來刪
指令有三種DELETE ,TRUNCATE ,DROP
1.
DELETE是DML指令,可以配合WHERE來刪除特定的資料列
DELETE後的資料可以用COMMIT確認刪除或是用ROLLBACK回復刪除的資料
語法是:
DELETE FROM 資料表 WHERE 某欄位='ABC'
2.
TRUNCATE是DDL指令,用了之後刪掉的資料不能回復,速度很快比DELETE還快,但是只能一次刪掉全部的資料表內容而不行指定要刪哪一列
語法是:
USE 資料庫的名字
TRUNCATE table 資料表的名字
就可以把資料表裡的內容都快速清空
3.
DROP是DDL指令,用了之後刪掉的資料不能回復,直接把資料表整個刪了,注意是連資料表都不見了喔
語法是:
DROP TABLE 資料表的名字
2010年9月21日 星期二
Asp.net 2.0 中将网站首页生成静态页的一个比较好的方法
做网站时,有时为了提高性能会将网站首页生成静态页(当然, Asp.net中页面缓存也是一个不错的选择了
将页面生成静态的方法有多中,据不完全统计有N种(N>1)
呵呵
代码如下
protected override void Render(HtmlTextWriter writer)
...{
System.IO.StringWriter html = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter tw = new HtmlTextWriter(html);
base.Render(tw);
System.IO.StreamWriter sw = new System.IO.StreamWriter(Server.MapPath("index.html"), false, System.Text.Encoding.Default);
sw.Write(html.ToString());
sw.Close();
tw.Close();
Response.Write("页面生成成功!");
}
将以上上函数数加如到你要生成静太文件的页面里,
函数从载了,Render函数 作用是把页面的 html文本截下来,保存到文件里,
进一步的可以去看一下asp.net页面生命过程.
静态页面的生成
protected override void Render(HtmlTextWriter writer) {
StreamWriter r=new StreamWriter(Server.MapPath(StaticFileName),
false,System.Text.Encoding.UTF8); //StaticFileName是html文件名
HtmlTextWriter h=new HtmlTextWriter(r);
base.Render(h);
r.Close();
h.Close();
Response.Redirect(StaticFileName);
}
然后在同一aspx的pageLoad事件中判断StaticFileName是否已经存在,如果存在,就应该直接转向,不应该继续生成页面了。还可将共方法定义到父类中,然后从配置文件中读取是否生成跳转等
将页面生成静态的方法有多中,据不完全统计有N种(N>1)
呵呵
代码如下
protected override void Render(HtmlTextWriter writer)
...{
System.IO.StringWriter html = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter tw = new HtmlTextWriter(html);
base.Render(tw);
System.IO.StreamWriter sw = new System.IO.StreamWriter(Server.MapPath("index.html"), false, System.Text.Encoding.Default);
sw.Write(html.ToString());
sw.Close();
tw.Close();
Response.Write("页面生成成功!");
}
将以上上函数数加如到你要生成静太文件的页面里,
函数从载了,Render函数 作用是把页面的 html文本截下来,保存到文件里,
进一步的可以去看一下asp.net页面生命过程.
静态页面的生成
protected override void Render(HtmlTextWriter writer) {
StreamWriter r=new StreamWriter(Server.MapPath(StaticFileName),
false,System.Text.Encoding.UTF8); //StaticFileName是html文件名
HtmlTextWriter h=new HtmlTextWriter(r);
base.Render(h);
r.Close();
h.Close();
Response.Redirect(StaticFileName);
}
然后在同一aspx的pageLoad事件中判断StaticFileName是否已经存在,如果存在,就应该直接转向,不应该继续生成页面了。还可将共方法定义到父类中,然后从配置文件中读取是否生成跳转等
IKVM.NET - Java 和 .NET 互通的工具
引用處
IKVM.NET 是在 .NET 上實作 JVM 的 Open Source Project。他可以讓你在 .NET 中使用 Java CLASS,也可以在 Java 中使用 NET。IKVM 主要包含三個部份:
1. .NET 上的 JVM 實作
2. .NET 實作版本的 Java Class Library
3. 賦予 Java 和 .NET 互通的工具
本文將透過 IKVM 進行簡單的互通測試
首先撰寫一個簡單的 Java 程式如下:
JavaToNet.java
public class JavaToNet
{
public static void main(String[] args)
{
System.out.println("This is a demonstration Program which\n");
System.out.println("shows the conversion of Java class to\n");
System.out.println("a .NET dll\n");
}
public String getAuthor(){
return "Chui-Wen Chiu(Arick)";
}
public static double AddNumbers(double a,double b){
double c = 0;
c = a + b;
return c;
}
// 產生 Exception
public static double hasException(){
return 1/0;
}
}
使用 Java SE5 的編譯器產生 CLASS
javac JavaToNet.java
然後使用 IKVM 產生 .NET Assembly
ikvmc -target:library JavaToNet.class
此時,我們已經擁有一個 .NET Assembly,接著撰寫一個簡單的測試程式如下:
dotNetTest.cs
using System;
using System.ComponentModel;
using System.Windows.Forms;
using TimeZone = java.util.TimeZone;
namespace WindowsApplication2
{
public class Program{
static void Main()
{
// 使用 java 內建類別
Console.WriteLine(TimeZone.getDefault().getDisplayName());
// 使用自訂類別靜態方法
Console.WriteLine(JavaToNet.AddNumbers(999, 888));
// 使用自訂類別物件方法
JavaToNet jt = new JavaToNet();
Console.WriteLine(jt.getAuthor());
// 引發 Exception
try{
JavaToNet.hasException();
}catch(System.DivideByZeroException ){
Console.WriteLine("Has Exception");
}
}
}
}
編譯程式
csc /r:JavaToNet.dll /r:IKVM.GNU.Classpath.dll dotNetTest.cs
執行OK
IKVM.NET 是在 .NET 上實作 JVM 的 Open Source Project。他可以讓你在 .NET 中使用 Java CLASS,也可以在 Java 中使用 NET。IKVM 主要包含三個部份:
1. .NET 上的 JVM 實作
2. .NET 實作版本的 Java Class Library
3. 賦予 Java 和 .NET 互通的工具
本文將透過 IKVM 進行簡單的互通測試
首先撰寫一個簡單的 Java 程式如下:
JavaToNet.java
public class JavaToNet
{
public static void main(String[] args)
{
System.out.println("This is a demonstration Program which\n");
System.out.println("shows the conversion of Java class to\n");
System.out.println("a .NET dll\n");
}
public String getAuthor(){
return "Chui-Wen Chiu(Arick)";
}
public static double AddNumbers(double a,double b){
double c = 0;
c = a + b;
return c;
}
// 產生 Exception
public static double hasException(){
return 1/0;
}
}
使用 Java SE5 的編譯器產生 CLASS
javac JavaToNet.java
然後使用 IKVM 產生 .NET Assembly
ikvmc -target:library JavaToNet.class
此時,我們已經擁有一個 .NET Assembly,接著撰寫一個簡單的測試程式如下:
dotNetTest.cs
using System;
using System.ComponentModel;
using System.Windows.Forms;
using TimeZone = java.util.TimeZone;
namespace WindowsApplication2
{
public class Program{
static void Main()
{
// 使用 java 內建類別
Console.WriteLine(TimeZone.getDefault().getDisplayName());
// 使用自訂類別靜態方法
Console.WriteLine(JavaToNet.AddNumbers(999, 888));
// 使用自訂類別物件方法
JavaToNet jt = new JavaToNet();
Console.WriteLine(jt.getAuthor());
// 引發 Exception
try{
JavaToNet.hasException();
}catch(System.DivideByZeroException ){
Console.WriteLine("Has Exception");
}
}
}
}
編譯程式
csc /r:JavaToNet.dll /r:IKVM.GNU.Classpath.dll dotNetTest.cs
執行OK
IKVM.NET Home Page
IKVM.NET 官網
IKVM.NET is an implementation of Java for Mono and the Microsoft .NET Framework. It includes the following components:
A Java Virtual Machine implemented in .NET
A .NET implementation of the Java class libraries
Tools that enable Java and .NET interoperability
IKVM.NET is an implementation of Java for Mono and the Microsoft .NET Framework. It includes the following components:
A Java Virtual Machine implemented in .NET
A .NET implementation of the Java class libraries
Tools that enable Java and .NET interoperability
2010年9月20日 星期一
关闭主窗体而不退出主程序 以及如何获取操作系统的关闭、注销信息
引用處
如何做到点击主窗体"X"按钮,能隐藏窗体,而不退出主程序?让我们先来分析窗体所响应的几个事件的先后顺序:
一. 当前用户点击窗体"关闭",右上角上的"X"图标时的系统消息的响应顺序是:
1. 系统截获用户的点击消息,可通过重载 WndProc截获;
2. 触发窗体的 FormClosing 事件;
3. 关闭窗体,回收本窗体所占用的相应资源;
二. 当在程序中用 this.Close() 关闭窗体时,系统响应的顺序是:
1. 触发窗体的 FormClosing 事件;
2. 关闭窗体,回收本窗体所占用的相应资源;
三. 当用户关闭操作系统时,窗体响应的顺序是:
1. 触发窗体的 FormClosing 事件;
2. 触发窗体的 SystemEvents_SessionEnding 事件;
3. 关闭窗体,回收本窗体所占用的相应资源;
因此当我们希望在点击主窗体"X"图标时,不希望程序退出,而只是最小化并隐藏窗体,则最好是通过重载 WndProc,截获点击该按钮事件,实现窗体最小化,从而达到不退出主程序的目的.
而不是简单的在FormClosing 事件中加上 e.Cancel=true; 那样在关闭或注销系统时,就不能自动关闭该窗体(程序)了;
经过以上分析,我们只需在窗体中加上以下代码即可:
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
{
this.WindowState = FormWindowState.Minimized;
this.Hide();
MessageBox.Show("click close button");
return;
}
base.WndProc(ref m);
}
四. 截获系统的关闭,注销信息
只需在程序Main()函数中为主窗体添加SystemEvents_SessionEnding事件;
Form1 frmMain = new Form1();
SystemEvents.SessionEnding += new SessionEndingEventHandler(frmMain.SystemEvents_SessionEnding);
在Form1 窗体中添加如下代码,以响应关机,注销或重启事件:
internal void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
string exitType = e.Reason.ToString().Trim().ToUpper();
MessageBox.Show(exitType);
string msgTitle = "";
string msgQuestion = "";
if (exitType.Contains("SHUTDOWN"))
{
msgTitle = "关机";
msgQuestion = "真的要关机吗?";
}
else if (exitType.Contains("LOGOFF"))
{
msgTitle = "注销";
msgQuestion = "真的要注销吗?";
}
DialogResult result = MessageBox.Show(msgQuestion , msgTitle , MessageBoxButtons.YesNo);
e.Cancel = (result == DialogResult.No);
}
补充说明:
SystemEvents 类 (用于提供对系统事件通知的访问。)来获取用户注销或关闭系统信息;
可查看MSDN说明;
如何做到点击主窗体"X"按钮,能隐藏窗体,而不退出主程序?让我们先来分析窗体所响应的几个事件的先后顺序:
一. 当前用户点击窗体"关闭",右上角上的"X"图标时的系统消息的响应顺序是:
1. 系统截获用户的点击消息,可通过重载 WndProc截获;
2. 触发窗体的 FormClosing 事件;
3. 关闭窗体,回收本窗体所占用的相应资源;
二. 当在程序中用 this.Close() 关闭窗体时,系统响应的顺序是:
1. 触发窗体的 FormClosing 事件;
2. 关闭窗体,回收本窗体所占用的相应资源;
三. 当用户关闭操作系统时,窗体响应的顺序是:
1. 触发窗体的 FormClosing 事件;
2. 触发窗体的 SystemEvents_SessionEnding 事件;
3. 关闭窗体,回收本窗体所占用的相应资源;
因此当我们希望在点击主窗体"X"图标时,不希望程序退出,而只是最小化并隐藏窗体,则最好是通过重载 WndProc,截获点击该按钮事件,实现窗体最小化,从而达到不退出主程序的目的.
而不是简单的在FormClosing 事件中加上 e.Cancel=true; 那样在关闭或注销系统时,就不能自动关闭该窗体(程序)了;
经过以上分析,我们只需在窗体中加上以下代码即可:
protected override void WndProc(ref Message m)
{
const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;
if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
{
this.WindowState = FormWindowState.Minimized;
this.Hide();
MessageBox.Show("click close button");
return;
}
base.WndProc(ref m);
}
四. 截获系统的关闭,注销信息
只需在程序Main()函数中为主窗体添加SystemEvents_SessionEnding事件;
Form1 frmMain = new Form1();
SystemEvents.SessionEnding += new SessionEndingEventHandler(frmMain.SystemEvents_SessionEnding);
在Form1 窗体中添加如下代码,以响应关机,注销或重启事件:
internal void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
string exitType = e.Reason.ToString().Trim().ToUpper();
MessageBox.Show(exitType);
string msgTitle = "";
string msgQuestion = "";
if (exitType.Contains("SHUTDOWN"))
{
msgTitle = "关机";
msgQuestion = "真的要关机吗?";
}
else if (exitType.Contains("LOGOFF"))
{
msgTitle = "注销";
msgQuestion = "真的要注销吗?";
}
DialogResult result = MessageBox.Show(msgQuestion , msgTitle , MessageBoxButtons.YesNo);
e.Cancel = (result == DialogResult.No);
}
补充说明:
SystemEvents 类 (用于提供对系统事件通知的访问。)来获取用户注销或关闭系统信息;
可查看MSDN说明;
WinForm窗体FormClosing事件导致无法关机
使用C#做桌面开发,当点击右上角的关闭按钮时,希望程序不是关闭而是最小化到通知栏的时候,也许我们会使用 FormClosing 事件中来取消窗体的关闭。但这也会导致一个问题就是当程序运行的时候如果关闭电脑,则电脑无法正常关机。我么可以用以下方法来解决:
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.ToString() == "UserClosing")
{
e.Cancel=true
}
}
因为用户点击程序关闭和电脑控制程序关闭的“关闭窗体原因”是不一样的,所以可以利用此方法来解决。
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.ToString() == "UserClosing")
{
e.Cancel=true
}
}
因为用户点击程序关闭和电脑控制程序关闭的“关闭窗体原因”是不一样的,所以可以利用此方法来解决。
regedit My.Computer.Registry
微軟官網
Dim readValue As Object
readValue = My.Computer.Registry.GetValue _
("HKEY_CURRENT_USER\Software\MyApp", "Name", Nothing)
MsgBox("The value is " & CStr(readValue))
Dim readValue As Object
readValue = My.Computer.Registry.GetValue _
("HKEY_CURRENT_USER\Software\MyApp", "Name", Nothing)
MsgBox("The value is " & CStr(readValue))
regedit for Microsoft.Win32
'Example:
Imports Microsoft.Win32
'....
Dim regKey As RegistryKey, regSubKey As RegistryKey
'regKey now points to HKEY_LOCAL_MACHINE Registry Key
regKey = Registry.LocalMachine
'A Sub key called MyProgram is created under the
'HKEY_LOCAL_MACHINE key
regSubKey = regKey.CreateSubKey("Software\Microsoft\Windows\MyProgram")
'The value of the Key is set to Registered Owner and Organization
regSubKey.SetValue("RegisteredOwner", txtName.Text)
regSubKey.SetValue("RegisteredOrganization", txtCompany.Text)
Imports Microsoft.Win32
'....
Dim regKey As RegistryKey, regSubKey As RegistryKey
'regKey now points to HKEY_LOCAL_MACHINE Registry Key
regKey = Registry.LocalMachine
'A Sub key called MyProgram is created under the
'HKEY_LOCAL_MACHINE key
regSubKey = regKey.CreateSubKey("Software\Microsoft\Windows\MyProgram")
'The value of the Key is set to Registered Owner and Organization
regSubKey.SetValue("RegisteredOwner", txtName.Text)
regSubKey.SetValue("RegisteredOrganization", txtCompany.Text)
Regedit 讀取寫入
Option Explicit
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_PERFORMANCE_DATA = &H80000004
Const ERROR_BADKEY = 2
Const ERROR_ACCESS_DENIED = 8
Const ERROR_SUCCESS = 0
Dim xpass '註冊碼
Dim Y '使用者 主機版機碼
'結果
'
'位置:SYSTEM\ControlSet001\Control\Windows
'下有 8 個子鍵:
'------------------------------
'鍵名:CSDVersion 型態:REG_DWORD 內容:768
'鍵名:CSDReleaseType 型態:REG_DWORD 內容:0
'鍵名:Directory 型態:REG_EXPAND_SZ 內容:C:\WINDOWS
'鍵名:ErrorMode 型態:REG_DWORD 內容:0
'鍵名:NoInteractiveServices 型態:REG_DWORD 內容:0
'鍵名:SystemDirectory 型態:REG_EXPAND_SZ 內容:C:\WINDOWS\system32
'鍵名:ShellErrorMode 型態:REG_DWORD 內容:1
'鍵名:ShutdownTime 型態:REG_BINARY 內容:C4 82 71 D0 38 6E C9 01
Private Function Get_MB_SNo() As String
Dim strCls As String, strKey As String
Dim WMI As Object
Set WMI = GetObject("winmgmts:")
strCls = "Win32_BaseBoard" ' WMI 類別
strKey = strCls & ".Tag=""Base Board"""
Get_MB_SNo = Trim(WMI.InstancesOf(strCls)(strKey).SerialNumber)
End Function
Private Sub Command1_Click()
Dim REGIFSN
'讀取REGEDIT的 HKEY_CURRENT_USER\Software\VB and VBA Program Settings\專案一\Settings MainHeight的值
REGIFSN = GetSetting("專案一", "SETTINGS", "MainHeight")
If Val(REGIFSN) <> xpass Then
MsgBox Y
Else
MsgBox "恭喜通過註冊"
End If
' Print "主機板序號 : " & Get_MB_SNo
End Sub
Private Sub Command2_Click()
'存入REGEDIT的 HKEY_CURRENT_USER\Software\VB and VBA Program Settings\專案一\Settings MainHeight的值
SaveSetting "專案一", "SETTINGS", "MainHeight", xpass
End Sub
Private Sub Command3_Click()
Msgbox y '秀出原始數字
'秀出正確密碼
MsgBox xpass
End Sub
Private Sub Form_Load()
Dim i
Y = 0
For i = 1 To Len(Trim(Get_MB_SNo))
Y = Y + Asc(Mid(Get_MB_SNo, i))
Next i
Y = Y * 125
xpass =Y+99
'在form_load就算好密碼
Debug.Print xpass
End Sub
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_PERFORMANCE_DATA = &H80000004
Const ERROR_BADKEY = 2
Const ERROR_ACCESS_DENIED = 8
Const ERROR_SUCCESS = 0
Dim xpass '註冊碼
Dim Y '使用者 主機版機碼
'結果
'
'位置:SYSTEM\ControlSet001\Control\Windows
'下有 8 個子鍵:
'------------------------------
'鍵名:CSDVersion 型態:REG_DWORD 內容:768
'鍵名:CSDReleaseType 型態:REG_DWORD 內容:0
'鍵名:Directory 型態:REG_EXPAND_SZ 內容:C:\WINDOWS
'鍵名:ErrorMode 型態:REG_DWORD 內容:0
'鍵名:NoInteractiveServices 型態:REG_DWORD 內容:0
'鍵名:SystemDirectory 型態:REG_EXPAND_SZ 內容:C:\WINDOWS\system32
'鍵名:ShellErrorMode 型態:REG_DWORD 內容:1
'鍵名:ShutdownTime 型態:REG_BINARY 內容:C4 82 71 D0 38 6E C9 01
Private Function Get_MB_SNo() As String
Dim strCls As String, strKey As String
Dim WMI As Object
Set WMI = GetObject("winmgmts:")
strCls = "Win32_BaseBoard" ' WMI 類別
strKey = strCls & ".Tag=""Base Board"""
Get_MB_SNo = Trim(WMI.InstancesOf(strCls)(strKey).SerialNumber)
End Function
Private Sub Command1_Click()
Dim REGIFSN
'讀取REGEDIT的 HKEY_CURRENT_USER\Software\VB and VBA Program Settings\專案一\Settings MainHeight的值
REGIFSN = GetSetting("專案一", "SETTINGS", "MainHeight")
If Val(REGIFSN) <> xpass Then
MsgBox Y
Else
MsgBox "恭喜通過註冊"
End If
' Print "主機板序號 : " & Get_MB_SNo
End Sub
Private Sub Command2_Click()
'存入REGEDIT的 HKEY_CURRENT_USER\Software\VB and VBA Program Settings\專案一\Settings MainHeight的值
SaveSetting "專案一", "SETTINGS", "MainHeight", xpass
End Sub
Private Sub Command3_Click()
Msgbox y '秀出原始數字
'秀出正確密碼
MsgBox xpass
End Sub
Private Sub Form_Load()
Dim i
Y = 0
For i = 1 To Len(Trim(Get_MB_SNo))
Y = Y + Asc(Mid(Get_MB_SNo, i))
Next i
Y = Y * 125
xpass =Y+99
'在form_load就算好密碼
Debug.Print xpass
End Sub
防止重複執行
Dim ProcessName As String = Process.GetCurrentProcess.ProcessName
Dim runp As Process()
runp = Process.GetProcessesByName(ProcessName)
If runp.Length > 1 Then
'重複時,處理程序
End If
Dim runp As Process()
runp = Process.GetProcessesByName(ProcessName)
If runp.Length > 1 Then
'重複時,處理程序
End If
2010年9月19日 星期日
2010年9月18日 星期六
access Image 型態 Ole 物件
string connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Rajesh\SampleDB_2003.mdb;";
OleDbConnection oConn = new OleDbConnection(connString);
oConn.Open();
string commandString = "select * from employee where id = " + id + "";
OleDbCommand oCmd = new OleDbCommand(commandString, oConn);
OleDbDataReader oReader = oCmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (oReader.Read())
{
txtID.Text = ((int)oReader.GetValue(0)).ToString();
txtName.Text = (string)oReader.GetValue(1);
txtAge.Text = ((int)oReader.GetValue(2)).ToString();
txtType.Text = (string)oReader.GetValue(3);
byte[] imageBytes = (byte[])oReader.GetValue(4);
MemoryStream ms = new MemoryStream();
ms.Write(imageBytes, 0, imageBytes.Length);
Bitmap bmp = new Bitmap(ms);
pbPassport.Image = Image.FromStream(ms);
}
OleDbConnection oConn = new OleDbConnection(connString);
oConn.Open();
string commandString = "select * from employee where id = " + id + "";
OleDbCommand oCmd = new OleDbCommand(commandString, oConn);
OleDbDataReader oReader = oCmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (oReader.Read())
{
txtID.Text = ((int)oReader.GetValue(0)).ToString();
txtName.Text = (string)oReader.GetValue(1);
txtAge.Text = ((int)oReader.GetValue(2)).ToString();
txtType.Text = (string)oReader.GetValue(3);
byte[] imageBytes = (byte[])oReader.GetValue(4);
MemoryStream ms = new MemoryStream();
ms.Write(imageBytes, 0, imageBytes.Length);
Bitmap bmp = new Bitmap(ms);
pbPassport.Image = Image.FromStream(ms);
}
2010年9月17日 星期五
Table variables
引用處
Table Variables
Table variables are objects similar to temporary tables and were introduced in SQL Server 2000. A table variable is declared using the table data type. A statement declaring a table variable initializes the variable as an empty table with a specified structure. As a table definition, such a statement includes definitions of columns with their data type, size, precision, and optional constraints (primary key, identity, unique, and check constraints). All elements have to be defined during the declaration. It is not possible to alter or add them later.
The following batch declares a table variable, inserts rows, and returns them to the user:
Declare @MyTableVar table
(Id int primary key,
Lookup varchar(15))
Insert @MyTableVar values (1, '1Q2000')
Insert @MyTableVar values (2, '2Q2000')
Insert @MyTableVar values (3, '3Q2000')
Select * from @MyTableVar
GoBecause of their nature, table variables have certain limitations:
Table variables can only be part of the Select, Update, Delete, Insert, and Declare Cursor statements.
Table variables can be used as a part of the Select statement everywhere tables are acceptable, except as the destination in a Select...Into statement:
Select LookupId, Lookup
Into @TableVariable -- wrong
From LookupTable variables can be used in Insert statements except when the Insert statement collects values from a stored procedure:
Insert into @TableVariable -- wrong
Exec prMyProcedure
Unlike temporary tables, table variables always have a local scope. They can be used only in the batch, stored procedure, or function in which they are declared.
Table variables are considered to be nonpersistent objects, and therefore they will not be rolled back after a Rollback Transaction statement.
Table Variables
Table variables are objects similar to temporary tables and were introduced in SQL Server 2000. A table variable is declared using the table data type. A statement declaring a table variable initializes the variable as an empty table with a specified structure. As a table definition, such a statement includes definitions of columns with their data type, size, precision, and optional constraints (primary key, identity, unique, and check constraints). All elements have to be defined during the declaration. It is not possible to alter or add them later.
The following batch declares a table variable, inserts rows, and returns them to the user:
Declare @MyTableVar table
(Id int primary key,
Lookup varchar(15))
Insert @MyTableVar values (1, '1Q2000')
Insert @MyTableVar values (2, '2Q2000')
Insert @MyTableVar values (3, '3Q2000')
Select * from @MyTableVar
GoBecause of their nature, table variables have certain limitations:
Table variables can only be part of the Select, Update, Delete, Insert, and Declare Cursor statements.
Table variables can be used as a part of the Select statement everywhere tables are acceptable, except as the destination in a Select...Into statement:
Select LookupId, Lookup
Into @TableVariable -- wrong
From LookupTable variables can be used in Insert statements except when the Insert statement collects values from a stored procedure:
Insert into @TableVariable -- wrong
Exec prMyProcedure
Unlike temporary tables, table variables always have a local scope. They can be used only in the batch, stored procedure, or function in which they are declared.
Table variables are considered to be nonpersistent objects, and therefore they will not be rolled back after a Rollback Transaction statement.
DECLARE @local_variable table
微軟官網
USE AdventureWorks;
GO
DECLARE @MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25
OUTPUT INSERTED.EmployeeID,
DELETED.VacationHours,
INSERTED.VacationHours,
INSERTED.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
--Note that ModifiedDate reflects the value generated by an
--AFTER UPDATE trigger.
SELECT TOP (10) EmployeeID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
USE AdventureWorks;
GO
DECLARE @MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25
OUTPUT INSERTED.EmployeeID,
DELETED.VacationHours,
INSERTED.VacationHours,
INSERTED.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
--Note that ModifiedDate reflects the value generated by an
--AFTER UPDATE trigger.
SELECT TOP (10) EmployeeID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
declare @xx table
我真是淺了,現在才知道SQL有這記憶體虛擬表可運用
截至現在,都還是拉到程式內再放到datatable or dataset內後;來處理其它運用
===
declare @xx table (fieldname1 varchar(1),xxx)
底下為收集了相關:(因我自己也要參用)
===
DECLARE @TmpTable TABLE (
FirstName varchar(20),
LastName varchar(20)
)
建立一個 table 資料型別的暫存資料表,它是存在記憶體中的。因此其他人無法看到,此外當定義 table 資料型別的函數、預存程序或批次結束時,就會自動清除這個暫存資料表。
===
在SQL中声明一个表变量,使用Declare @table Table,即可对这个变量进行表的操作.
如下所示,声明@user变量,然后插入数据.
Declare @user Table
(
ID INT,
NAME NVARCHAR(15)
)
Insert INTO @table(ID,NAME)
Select ID,NAME
FROM USER
===
(单号 char(5),款号 CHAR(3), 系列号 CHAR(5), 数量 INT, 生产日期 CHAR(10))
INSERT @a SELECT 'A1211','F11','2042N',10,'20100901'
UNION ALL SELECT 'A1212','F12','2042N',20,'20100901'
UNION ALL SELECT 'A1211','F11','3044N',10,'20100901'
UNION ALL SELECT 'A1213','F13','2042N',10,'20100901'
UNION ALL SELECT 'A1211','F11','2042N',20,'20100902'
UNION ALL SELECT 'A1214','F11','2011A',10,'20100901'
UNION ALL SELECT 'A1212','F11','2045N',10,'20100903'
UNION ALL SELECT 'A1213','F12','2045N',20,'20100903'
DECLARE @b TABLE (单号 char(5),款号 CHAR(3), 系列号 CHAR(5), 数量 INT, 出货日期 CHAR(10))
INSERT @b SELECT 'A1211','F11','2042N',10,'20100910'
UNION ALL SELECT 'A1212','F12','2042N',20,'20100912'
UNION ALL SELECT 'A1211','F11','3044N',10,'20100912'
UNION ALL SELECT 'A1213','F13','2042N',10,'20100912'
UNION ALL SELECT 'A1214','F11','2011A',10,'20100912'
UNION ALL SELECT 'A1211','F22','2042N',10,'20100913'
--从A表中取出相同生产日,相同系列号,不同单号的数据
SELECT *
FROM @a a
WHERE a.生产日期 IN (SELECT 生产日期 FROM @a GROUP BY 生产日期 HAVING COUNT(生产日期)>1 )
AND a.系列号 IN (SELECT 系列号 FROM @a GROUP BY 系列号 HAVING COUNT(系列号)>1)
--单号 款号 系列号 数量 生产日期
------- ---- ----- ----------- ----------
--A1211 F11 2042N 10 20100901
--A1212 F12 2042N 20 20100901
--A1213 F13 2042N 10 20100901
--A1212 F11 2045N 10 20100903
--A1213 F12 2045N 20 20100903
--
--(5 行受影响)
SELECT a.*,ISNULL(b.出货日期,'没有出货') AS 出货日期
FROM @a a
LEFT JOIN (SELECT 单号,系列号,MIN(出货日期) AS 出货日期 FROM @b GROUP BY 单号,系列号) b ON a.单号 = b.单号 AND a.系列号 = b.系列号
WHERE a.生产日期 IN (SELECT 生产日期 FROM @a GROUP BY 生产日期 HAVING COUNT(生产日期)>1 )
AND a.系列号 IN (SELECT 系列号 FROM @a GROUP BY 系列号 HAVING COUNT(系列号)>1)
--查询结果
--单号 款号 系列号 数量 生产日期 出货日期
------- ---- ----- ----------- ---------- ----------
--A1211 F11 2042N 10 20100901 20100910
--A1212 F12 2042N 20 20100901 20100912
--A1213 F13 2042N 10 20100901 20100912
--A1212 F11 2045N 10 20100903 没有出货
--A1213 F12 2045N 20 20100903 没有出货
--
--(5 行受影响)
截至現在,都還是拉到程式內再放到datatable or dataset內後;來處理其它運用
===
declare @xx table (fieldname1 varchar(1),xxx)
底下為收集了相關:(因我自己也要參用)
===
DECLARE @TmpTable TABLE (
FirstName varchar(20),
LastName varchar(20)
)
建立一個 table 資料型別的暫存資料表,它是存在記憶體中的。因此其他人無法看到,此外當定義 table 資料型別的函數、預存程序或批次結束時,就會自動清除這個暫存資料表。
===
在SQL中声明一个表变量,使用Declare @table Table,即可对这个变量进行表的操作.
如下所示,声明@user变量,然后插入数据.
Declare @user Table
(
ID INT,
NAME NVARCHAR(15)
)
Insert INTO @table(ID,NAME)
Select ID,NAME
FROM USER
===
(单号 char(5),款号 CHAR(3), 系列号 CHAR(5), 数量 INT, 生产日期 CHAR(10))
INSERT @a SELECT 'A1211','F11','2042N',10,'20100901'
UNION ALL SELECT 'A1212','F12','2042N',20,'20100901'
UNION ALL SELECT 'A1211','F11','3044N',10,'20100901'
UNION ALL SELECT 'A1213','F13','2042N',10,'20100901'
UNION ALL SELECT 'A1211','F11','2042N',20,'20100902'
UNION ALL SELECT 'A1214','F11','2011A',10,'20100901'
UNION ALL SELECT 'A1212','F11','2045N',10,'20100903'
UNION ALL SELECT 'A1213','F12','2045N',20,'20100903'
DECLARE @b TABLE (单号 char(5),款号 CHAR(3), 系列号 CHAR(5), 数量 INT, 出货日期 CHAR(10))
INSERT @b SELECT 'A1211','F11','2042N',10,'20100910'
UNION ALL SELECT 'A1212','F12','2042N',20,'20100912'
UNION ALL SELECT 'A1211','F11','3044N',10,'20100912'
UNION ALL SELECT 'A1213','F13','2042N',10,'20100912'
UNION ALL SELECT 'A1214','F11','2011A',10,'20100912'
UNION ALL SELECT 'A1211','F22','2042N',10,'20100913'
--从A表中取出相同生产日,相同系列号,不同单号的数据
SELECT *
FROM @a a
WHERE a.生产日期 IN (SELECT 生产日期 FROM @a GROUP BY 生产日期 HAVING COUNT(生产日期)>1 )
AND a.系列号 IN (SELECT 系列号 FROM @a GROUP BY 系列号 HAVING COUNT(系列号)>1)
--单号 款号 系列号 数量 生产日期
------- ---- ----- ----------- ----------
--A1211 F11 2042N 10 20100901
--A1212 F12 2042N 20 20100901
--A1213 F13 2042N 10 20100901
--A1212 F11 2045N 10 20100903
--A1213 F12 2045N 20 20100903
--
--(5 行受影响)
SELECT a.*,ISNULL(b.出货日期,'没有出货') AS 出货日期
FROM @a a
LEFT JOIN (SELECT 单号,系列号,MIN(出货日期) AS 出货日期 FROM @b GROUP BY 单号,系列号) b ON a.单号 = b.单号 AND a.系列号 = b.系列号
WHERE a.生产日期 IN (SELECT 生产日期 FROM @a GROUP BY 生产日期 HAVING COUNT(生产日期)>1 )
AND a.系列号 IN (SELECT 系列号 FROM @a GROUP BY 系列号 HAVING COUNT(系列号)>1)
--查询结果
--单号 款号 系列号 数量 生产日期 出货日期
------- ---- ----- ----------- ---------- ----------
--A1211 F11 2042N 10 20100901 20100910
--A1212 F12 2042N 20 20100901 20100912
--A1213 F13 2042N 10 20100901 20100912
--A1212 F11 2045N 10 20100903 没有出货
--A1213 F12 2045N 20 20100903 没有出货
--
--(5 行受影响)
2010年9月16日 星期四
多個1維陣列合併
==code===
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim a(9) As Integer
Dim b(9) As Integer
For i As Integer = 0 To 9
a(i) = i
Next
For i As Integer = 0 To 9
b(i) = i + 10
Next
Dim temp As New List(Of Integer)
temp.AddRange(a)
temp.AddRange(b)
Dim all As Integer() = temp.ToArray
ListBox1.Items.Clear()
For i As Integer = 0 To UBound(all)
ListBox1.Items.Add(all(i).ToString)
Next
End Sub
2010年9月14日 星期二
SqlBulkCopy 构造函数 (String, SqlBulkCopyOptions)
下面的控制台应用程序演示如何使用一个指定为字符串的连接执行批量加载。其中设置了一个选项以在加载目标表时使用源表的标识列中的值。在此示例中,首先将 SQL Server 表中的源数据读取到 SqlDataReader 实例。源表和目标表中各包括一个“标识”列。默认情况下,在目标表中会为每个添加的行生成一个新的“标识”列值。此示例设置一个选项以在打开强制执行批量加载进程的连接时使用源表的“标识”值。若要了解此选项如何改变批量加载的工作方式,请在 dbo.BulkCopyDemoMatchingColumns 表为空的情况下运行该示例。所有行均从源处加载。然后再次运行示例而不清空表。这将引发异常,并且代码会在控制台中写入一条消息,通知您由于主键违反约束尚未添加行。
Imports System.Data.SqlClient
Module Module1
Sub Main()
Dim connectionString As String = GetConnectionString()
' Open a connection to the AdventureWorks database.
Using sourceConnection As SqlConnection = _
New SqlConnection(connectionString)
sourceConnection.Open()
' Perform an initial count on the destination table.
Dim commandRowCount As New SqlCommand( _
"SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
sourceConnection)
Dim countStart As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Starting row count = {0}", countStart)
' Get data from the source table as a SqlDataReader.
Dim commandSourceData As SqlCommand = New SqlCommand( _
"SELECT ProductID, Name, ProductNumber " & _
"FROM Production.Product;", sourceConnection)
Dim reader As SqlDataReader = commandSourceData.ExecuteReader
' Create the SqlBulkCopy object using a connection string
' and the KeepIdentity option.
' In the real world you would not use SqlBulkCopy to move
' data from one table to the other in the same database.
Using bulkCopy As SqlBulkCopy = _
New SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity)
bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"
Try
' Write from the source to the destination.
bulkCopy.WriteToServer(reader)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
' Close the SqlDataReader. The SqlBulkCopy
' object is automatically closed at the end
' of the Using block.
reader.Close()
End Try
End Using
' Perform a final count on the destination table
' to see how many rows were added.
Dim countEnd As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Ending row count = {0}", countEnd)
Console.WriteLine("{0} rows were added.", countEnd - countStart)
Console.WriteLine("Press Enter to finish.")
Console.ReadLine()
End Using
End Sub
Private Function GetConnectionString() As String
' To avoid storing the sourceConnection string in your code,
' you can retrieve it from a configuration file.
Return "Data Source=(local);" & _
"Integrated Security=true;" & _
"Initial Catalog=AdventureWorks;"
End Function
End Module
Imports System.Data.SqlClient
Module Module1
Sub Main()
Dim connectionString As String = GetConnectionString()
' Open a connection to the AdventureWorks database.
Using sourceConnection As SqlConnection = _
New SqlConnection(connectionString)
sourceConnection.Open()
' Perform an initial count on the destination table.
Dim commandRowCount As New SqlCommand( _
"SELECT COUNT(*) FROM dbo.BulkCopyDemoMatchingColumns;", _
sourceConnection)
Dim countStart As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Starting row count = {0}", countStart)
' Get data from the source table as a SqlDataReader.
Dim commandSourceData As SqlCommand = New SqlCommand( _
"SELECT ProductID, Name, ProductNumber " & _
"FROM Production.Product;", sourceConnection)
Dim reader As SqlDataReader = commandSourceData.ExecuteReader
' Create the SqlBulkCopy object using a connection string
' and the KeepIdentity option.
' In the real world you would not use SqlBulkCopy to move
' data from one table to the other in the same database.
Using bulkCopy As SqlBulkCopy = _
New SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity)
bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"
Try
' Write from the source to the destination.
bulkCopy.WriteToServer(reader)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
' Close the SqlDataReader. The SqlBulkCopy
' object is automatically closed at the end
' of the Using block.
reader.Close()
End Try
End Using
' Perform a final count on the destination table
' to see how many rows were added.
Dim countEnd As Long = _
System.Convert.ToInt32(commandRowCount.ExecuteScalar())
Console.WriteLine("Ending row count = {0}", countEnd)
Console.WriteLine("{0} rows were added.", countEnd - countStart)
Console.WriteLine("Press Enter to finish.")
Console.ReadLine()
End Using
End Sub
Private Function GetConnectionString() As String
' To avoid storing the sourceConnection string in your code,
' you can retrieve it from a configuration file.
Return "Data Source=(local);" & _
"Integrated Security=true;" & _
"Initial Catalog=AdventureWorks;"
End Function
End Module
SqlBulkCopy(大数据量拷贝)
///
/// 批量执行SqlBulkCopy数据迁移操作
///
/// 数据源
/// 执行前需要执行的脚本,如先清空表等,可为空
/// 目标数据库表名称
///
public static bool ExeSqlBulkCopy(DataTable dtblSource, string strPreSqlSentence,string strDestinationTablesName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
bool blReturnValue = false; connection.Open();
//请在插入数据的同时检查约束,如果发生错误调用 sqlbulkTransaction事务
SqlTransaction sqlbulkTransaction = connection.BeginTransaction();
if (strPreSqlSentence != "")
{
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.Connection = connection; sqlCmd.Transaction = sqlbulkTransaction;
try
{
sqlCmd.CommandText = strPreSqlSentence; sqlCmd.ExecuteNonQuery(); blReturnValue = true;
}
catch (Exception exc)
{
Log.WriteLog("批量插入前语句失败", exc); sqlbulkTransaction.Rollback(); connection.Close(); return false;
}
}
SqlBulkCopy BulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.CheckConstraints, sqlbulkTransaction);
BulkCopy.DestinationTableName = strDestinationTablesName; BulkCopy.BulkCopyTimeout = 1200;
try
{
BulkCopy.WriteToServer(dtblSource); sqlbulkTransaction.Commit(); blReturnValue = true;
}
catch (Exception exp)
{
sqlbulkTransaction.Rollback(); Log.WriteLog("批量插入语句失败", exp); blReturnValue = false;
}
finally
{
BulkCopy.Close(); connection.Close();
}
return blReturnValue;
}
}
/// 批量执行SqlBulkCopy数据迁移操作
///
/// 数据源
/// 执行前需要执行的脚本,如先清空表等,可为空
/// 目标数据库表名称
///
public static bool ExeSqlBulkCopy(DataTable dtblSource, string strPreSqlSentence,string strDestinationTablesName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
bool blReturnValue = false; connection.Open();
//请在插入数据的同时检查约束,如果发生错误调用 sqlbulkTransaction事务
SqlTransaction sqlbulkTransaction = connection.BeginTransaction();
if (strPreSqlSentence != "")
{
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.Connection = connection; sqlCmd.Transaction = sqlbulkTransaction;
try
{
sqlCmd.CommandText = strPreSqlSentence; sqlCmd.ExecuteNonQuery(); blReturnValue = true;
}
catch (Exception exc)
{
Log.WriteLog("批量插入前语句失败", exc); sqlbulkTransaction.Rollback(); connection.Close(); return false;
}
}
SqlBulkCopy BulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.CheckConstraints, sqlbulkTransaction);
BulkCopy.DestinationTableName = strDestinationTablesName; BulkCopy.BulkCopyTimeout = 1200;
try
{
BulkCopy.WriteToServer(dtblSource); sqlbulkTransaction.Commit(); blReturnValue = true;
}
catch (Exception exp)
{
sqlbulkTransaction.Rollback(); Log.WriteLog("批量插入语句失败", exp); blReturnValue = false;
}
finally
{
BulkCopy.Close(); connection.Close();
}
return blReturnValue;
}
}
2010年9月13日 星期一
在你的VB.NET應用程序中使用多線程
很長時間以來,開發人員一直要求微軟為VB增加更多的線程功能——這一點在VB.NET中終於實現了。VB6不支持創建多線程的EXE、DLL以及OCX。但這種措詞容易引起誤解,這是因為VB6支持執行多個單線程的單元。一個單元實際上是代碼執行的場所而且單元的邊界限制了外部代碼對單元內部的訪問。
VB.NET支持創建自由線程的應用程序。這意味著多個線程可以訪問同一個共享的數據集。本文將帶領你瞭解多線程的基本內容。
雖然VB支持多個單線程的單元,但並不支持允許多個線程在同一個數據集上運行的自由線程模型。在很多情況下,產生一個運行後台處理程序的新線程會提高應用程序的可用性。一種很顯然的情況就是當執行一個可能使窗體看起來停止響應的長過程時,你一定會想在窗體上放置一個取消按鈕。
解決方法
由於VB.NET使用公共語言運行時(Common Language Runtime),它增強了很多新的特性,其中之一便是創建自由線程應用程序的能力。
在VB.NET中,開始使利用線程進行工作是很容易的。稍後我們會探究一些精妙之處,我們先創建一個簡單的窗體,它生成一個執行後台處理程序的新線程。我們需要做的第一件事是將要在新線程上運行的後台處理程序。下面的代碼執行一個相當長的運行過程——一個無限循環:
Private Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Loop
End Sub
這段代碼無限地循環並在每次循環中向窗體上的列表框中增加一個條目。如果你對VB.NET不熟悉的話,便會發現這段代碼中有一些在VB6中無法完成的事:
l 在聲明變量時對其賦值 Dim i As Integer=1
l 使用+=操作符 i+=1代替了i=i+1
l Call關鍵字已經被去除了
一旦我們有了一個工作過程,便需要將這段代碼指派給一個新的線程並開始它的執行。完成這項工作,我們需要使用Thread對象,它是.NET框架類中System.Threading命名空間的一部分。當實例化了一個新的Thread類時,我們向其傳遞一個引用,這個引用指向我們想要在Thread類的構造函數中執行的代碼塊。下面的代碼創建一個新的Thread對象並將指向BackgroundProcess的引用傳遞給它:
Dim t As Thread
t = New Thread(AddressOf Me.BackgroundProcess)
t.Start()
AddressOf操作符為BackgroundProcess方法創建了一個委派對象。委派在VB.NET中是一種類型安全的、面向對象的函數指針。在線程被實例化之後,你可以通過調用線程的Start()方法開始執行代碼。
使線程處於控制之下
當線程開始之後,你可以通過使用Thread對象的方法對其狀態進行一定的控制。你可以通過調用Thread.Sleep方法暫停線程的執行。這個方法接收一個表示線程將要休眠多長時間的整型數值。如果在上例中你想要減緩列表框條目的添加,在代碼中放置一個對此方法的調用:
Private Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Thread.CurrentThread.Sleep(2000)
Loop
End Sub
CurrentThread是一個公共靜態屬性,它可以使你獲取一個對當前運行線程的引用。
你還可以通過調用Thread.Sleep (System.Threading.Timeout.Infinite)使一個線程處於一種時間不確定的休眠狀態。要中斷這種休眠,可以調用Thread.Interrupt 方法。
類似與Sleep和Interrupt的是Suspend和Resume。Suspend允許你阻塞一個線程直到另外的線程調用Thread.Resume。Sleep和Suspend之間的區別在於後者不是立即使一個線程處於等待狀態。在.NET運行時確定線程是處於一個安全的掛起位置之前,線程是不會掛起的。Sleep則是立即使線程進入等待狀態。
最後,Thread.Abort中止一個線程的執行。在我們的簡單例子中,我們還想增加另外一個可以使我們中止程序的按鈕。要完成這些,我們所需做的一切便是如下面這樣調用Thread.Abort方法:
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
t.Abort()
End Sub
在此便可以看出多線程的能力。用戶界面看起來對用戶是有響應的,因為它運行在一個線程中而後台的處理程序運行在另一個線程中。取消按鈕會立即響應用戶的click事件同時處理過程被中止。
通過多線程的過程傳遞數據
上一個例子展示了一種相當簡單的情況。在你編程的時候,多線程有很多需要解決的複雜問題。你將會遇到的一個問題是向傳遞給Thread類構造函數的過程傳遞數據以及從這個過程傳出數據。換言之,你想要在另一個線程上開始的過程不能接收任何參數而且你也不能從這個過程返回任何數據。這是因為傳遞給線程構造函數的過程不能有任何參數或返回值。為了避開這個問題,將你的過程包裝到一個類中,在這個類中此方法的參數被表示成類的一個域。
有一個簡單的例子,如果我們有一個計算一個數的平方的過程:
Function Square(ByVal Value As Double) As Double
Return Value * Value
End Function
為了使這個過程可以在一個新線程中使用,我們將其包裝到一個類中:
Public Class SquareClass
Public Value As Double
Public Square As Double
Public Sub CalcSquare()
Square = Value * Value
End Sub
End Class
使用這些代碼在一個新線程中啟動CalcSquare過程,代碼如下:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim oSquare As New SquareClass()
t = New Thread(AddressOf oSquare.CalcSquare)
oSquare.Value = 30
t.Start()
End Sub
注意當線程開始後,我們沒有檢查類的平方值,因為並不能保證一旦你調用線程Start方法,它便會執行。有一些方法可以從另外的線程中獲取這個值。最簡單的方法是當線程完成時引發一個事件。我們會在下一個部分線程同步中討論另外一種方法。下面的代碼為SquareClass增加了事件聲明。
Public Class SquareClass
Public Value As Double
Public Square As Double
Public Event ThreadComplete(ByVal Square As Double)
Public Sub CalcSquare()
Square = Value * Value
RaiseEvent ThreadComplete(Square)
End Sub
End Class
在調用代碼中捕獲這個事件與VB6相比沒有太大的變化,仍然是用WithEvents聲明變量並在一個過程中處理事件。變化的部分是用Handles關鍵字聲明處理事件的過程並且不再使用像VB6中Object_Event的命名約定。
Dim WithEvents oSquare As SquareClass
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
oSquare = New SquareClass()
t = New Thread(AddressOf oSquare.CalcSquare)
oSquare.Value = 30
t.Start()
End Sub
Sub SquareEventHandler(ByVal Square As Double) _
Handles oSquare.ThreadComplete
MsgBox("The square is " & Square)
End Sub
這個方法需要注意的一個問題是處理事件的過程,在本例中是SquareEventHandler,將運行在引發事件的線程中,而不是運行在窗體從中執行的線程中。
線程同步
VB.NET包含了一些語句用於提供線程的同步。在Square的例子中,你可能想同步執行計算的線程以便等到計算完成,這樣便可以獲得結果。舉另外一個例子,如果你在一個單獨的線程中對數組進行排序並且在使用這個數組之前要等待這個處理過程結束。為了實現這些同步,VB.NET提供了SyncLock語句和Thread.Join方法。
SyncLock獲取了對傳遞給它的對象引用的獨佔性鎖。通過取得這種獨佔鎖,你可以確保多個線程不會訪問共享的數據或是在多個線程上執行代碼。一個可以方便地用於獲取鎖地對象是關聯於每個類的System.Type對象。可以通過GetType方法獲得System.Type對像:
Public Sub CalcSquare()
SyncLock GetType(SquareClass)
Square = Value * Value
End SyncLock
End Sub
最後,Thread.Join方法允許你等待一段特定的時間直到一個線程結束。如果線程在你所確定的時間之前完成,Thread.Join返回True,否則的話返回False。在Square的例子中,如果我們不想引發事件,可以調用Thread.Join方法來確定計算是否已經結束。代碼如下所示:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim oSquare As New SquareClass()
t = New Thread(AddressOf oSquare.CalcSquare)
oSquare.Value = 30
t.Start()
If t.Join(500) Then
MsgBox(oSquare.Square)
End If
End Sub
VB.NET支持創建自由線程的應用程序。這意味著多個線程可以訪問同一個共享的數據集。本文將帶領你瞭解多線程的基本內容。
雖然VB支持多個單線程的單元,但並不支持允許多個線程在同一個數據集上運行的自由線程模型。在很多情況下,產生一個運行後台處理程序的新線程會提高應用程序的可用性。一種很顯然的情況就是當執行一個可能使窗體看起來停止響應的長過程時,你一定會想在窗體上放置一個取消按鈕。
解決方法
由於VB.NET使用公共語言運行時(Common Language Runtime),它增強了很多新的特性,其中之一便是創建自由線程應用程序的能力。
在VB.NET中,開始使利用線程進行工作是很容易的。稍後我們會探究一些精妙之處,我們先創建一個簡單的窗體,它生成一個執行後台處理程序的新線程。我們需要做的第一件事是將要在新線程上運行的後台處理程序。下面的代碼執行一個相當長的運行過程——一個無限循環:
Private Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Loop
End Sub
這段代碼無限地循環並在每次循環中向窗體上的列表框中增加一個條目。如果你對VB.NET不熟悉的話,便會發現這段代碼中有一些在VB6中無法完成的事:
l 在聲明變量時對其賦值 Dim i As Integer=1
l 使用+=操作符 i+=1代替了i=i+1
l Call關鍵字已經被去除了
一旦我們有了一個工作過程,便需要將這段代碼指派給一個新的線程並開始它的執行。完成這項工作,我們需要使用Thread對象,它是.NET框架類中System.Threading命名空間的一部分。當實例化了一個新的Thread類時,我們向其傳遞一個引用,這個引用指向我們想要在Thread類的構造函數中執行的代碼塊。下面的代碼創建一個新的Thread對象並將指向BackgroundProcess的引用傳遞給它:
Dim t As Thread
t = New Thread(AddressOf Me.BackgroundProcess)
t.Start()
AddressOf操作符為BackgroundProcess方法創建了一個委派對象。委派在VB.NET中是一種類型安全的、面向對象的函數指針。在線程被實例化之後,你可以通過調用線程的Start()方法開始執行代碼。
使線程處於控制之下
當線程開始之後,你可以通過使用Thread對象的方法對其狀態進行一定的控制。你可以通過調用Thread.Sleep方法暫停線程的執行。這個方法接收一個表示線程將要休眠多長時間的整型數值。如果在上例中你想要減緩列表框條目的添加,在代碼中放置一個對此方法的調用:
Private Sub BackgroundProcess()
Dim i As Integer = 1
Do While True
ListBox1.Items.Add("Iterations: " + i)
i += 1
Thread.CurrentThread.Sleep(2000)
Loop
End Sub
CurrentThread是一個公共靜態屬性,它可以使你獲取一個對當前運行線程的引用。
你還可以通過調用Thread.Sleep (System.Threading.Timeout.Infinite)使一個線程處於一種時間不確定的休眠狀態。要中斷這種休眠,可以調用Thread.Interrupt 方法。
類似與Sleep和Interrupt的是Suspend和Resume。Suspend允許你阻塞一個線程直到另外的線程調用Thread.Resume。Sleep和Suspend之間的區別在於後者不是立即使一個線程處於等待狀態。在.NET運行時確定線程是處於一個安全的掛起位置之前,線程是不會掛起的。Sleep則是立即使線程進入等待狀態。
最後,Thread.Abort中止一個線程的執行。在我們的簡單例子中,我們還想增加另外一個可以使我們中止程序的按鈕。要完成這些,我們所需做的一切便是如下面這樣調用Thread.Abort方法:
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
t.Abort()
End Sub
在此便可以看出多線程的能力。用戶界面看起來對用戶是有響應的,因為它運行在一個線程中而後台的處理程序運行在另一個線程中。取消按鈕會立即響應用戶的click事件同時處理過程被中止。
通過多線程的過程傳遞數據
上一個例子展示了一種相當簡單的情況。在你編程的時候,多線程有很多需要解決的複雜問題。你將會遇到的一個問題是向傳遞給Thread類構造函數的過程傳遞數據以及從這個過程傳出數據。換言之,你想要在另一個線程上開始的過程不能接收任何參數而且你也不能從這個過程返回任何數據。這是因為傳遞給線程構造函數的過程不能有任何參數或返回值。為了避開這個問題,將你的過程包裝到一個類中,在這個類中此方法的參數被表示成類的一個域。
有一個簡單的例子,如果我們有一個計算一個數的平方的過程:
Function Square(ByVal Value As Double) As Double
Return Value * Value
End Function
為了使這個過程可以在一個新線程中使用,我們將其包裝到一個類中:
Public Class SquareClass
Public Value As Double
Public Square As Double
Public Sub CalcSquare()
Square = Value * Value
End Sub
End Class
使用這些代碼在一個新線程中啟動CalcSquare過程,代碼如下:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim oSquare As New SquareClass()
t = New Thread(AddressOf oSquare.CalcSquare)
oSquare.Value = 30
t.Start()
End Sub
注意當線程開始後,我們沒有檢查類的平方值,因為並不能保證一旦你調用線程Start方法,它便會執行。有一些方法可以從另外的線程中獲取這個值。最簡單的方法是當線程完成時引發一個事件。我們會在下一個部分線程同步中討論另外一種方法。下面的代碼為SquareClass增加了事件聲明。
Public Class SquareClass
Public Value As Double
Public Square As Double
Public Event ThreadComplete(ByVal Square As Double)
Public Sub CalcSquare()
Square = Value * Value
RaiseEvent ThreadComplete(Square)
End Sub
End Class
在調用代碼中捕獲這個事件與VB6相比沒有太大的變化,仍然是用WithEvents聲明變量並在一個過程中處理事件。變化的部分是用Handles關鍵字聲明處理事件的過程並且不再使用像VB6中Object_Event的命名約定。
Dim WithEvents oSquare As SquareClass
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
oSquare = New SquareClass()
t = New Thread(AddressOf oSquare.CalcSquare)
oSquare.Value = 30
t.Start()
End Sub
Sub SquareEventHandler(ByVal Square As Double) _
Handles oSquare.ThreadComplete
MsgBox("The square is " & Square)
End Sub
這個方法需要注意的一個問題是處理事件的過程,在本例中是SquareEventHandler,將運行在引發事件的線程中,而不是運行在窗體從中執行的線程中。
線程同步
VB.NET包含了一些語句用於提供線程的同步。在Square的例子中,你可能想同步執行計算的線程以便等到計算完成,這樣便可以獲得結果。舉另外一個例子,如果你在一個單獨的線程中對數組進行排序並且在使用這個數組之前要等待這個處理過程結束。為了實現這些同步,VB.NET提供了SyncLock語句和Thread.Join方法。
SyncLock獲取了對傳遞給它的對象引用的獨佔性鎖。通過取得這種獨佔鎖,你可以確保多個線程不會訪問共享的數據或是在多個線程上執行代碼。一個可以方便地用於獲取鎖地對象是關聯於每個類的System.Type對象。可以通過GetType方法獲得System.Type對像:
Public Sub CalcSquare()
SyncLock GetType(SquareClass)
Square = Value * Value
End SyncLock
End Sub
最後,Thread.Join方法允許你等待一段特定的時間直到一個線程結束。如果線程在你所確定的時間之前完成,Thread.Join返回True,否則的話返回False。在Square的例子中,如果我們不想引發事件,可以調用Thread.Join方法來確定計算是否已經結束。代碼如下所示:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim oSquare As New SquareClass()
t = New Thread(AddressOf oSquare.CalcSquare)
oSquare.Value = 30
t.Start()
If t.Join(500) Then
MsgBox(oSquare.Square)
End If
End Sub
Abort a Thread
原出處
Imports System
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms
Imports System.IO
public class MainClass
Shared Sub Main()
Dim Thrd As Thread
Dim TStart As New ThreadStart(AddressOf BusyThread)
Thrd = New Thread(TStart)
Thrd.Priority = ThreadPriority.Highest
Thrd.Start()
Console.WriteLine(Thrd.ThreadState.ToString("G"))
Console.WriteLine("Thrd.IsAlive " & Thrd.IsAlive)
If Thrd.IsAlive Then
Thrd.Abort()
Thrd.Join()
End If
End Sub
Shared Sub BusyThread()
While True
'Console.Write("thread ")
End While
End Sub
End Class
Imports System
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms
Imports System.IO
public class MainClass
Shared Sub Main()
Dim Thrd As Thread
Dim TStart As New ThreadStart(AddressOf BusyThread)
Thrd = New Thread(TStart)
Thrd.Priority = ThreadPriority.Highest
Thrd.Start()
Console.WriteLine(Thrd.ThreadState.ToString("G"))
Console.WriteLine("Thrd.IsAlive " & Thrd.IsAlive)
If Thrd.IsAlive Then
Thrd.Abort()
Thrd.Join()
End If
End Sub
Shared Sub BusyThread()
While True
'Console.Write("thread ")
End While
End Sub
End Class
2010年9月11日 星期六
VB把文件存入/讀出數據庫IMAGE字段
1. VB把文件存入數據庫IMAGE字段
Sub savepic(FileName As String, IndexNumber As Long)
Dim DcnNWind As New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
DcnNWind.CursorLocation = adUseClient
DcnNWind.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER"
rs.CursorType = adOpenKeyset
rs.LockType = adLockOptimistic
rs.Open "CustomInfo", DcnNWind, , adCmdTable
rs.Move (IndexNumber)
Call FileToBlob(rs.Fields("Image"), FileName, FileLen(FileName))
rs.UpdateBatch adAffectCurrent
End Sub
Private Sub FileToBlob(fld As ADODB.Field, FileName As String, Optional ChunkSize As Long )
Dim fnum As Integer, bytesLeft As Long, bytes As Long
Dim tmp() As Byte
If (fld.Attributes And adFldLong) = 0 Then
Err.Raise 1001, , "Field doesn't support the GetChunk method."
End If
fnum = FreeFile
Open FileName For Binary As fnum
bytesLeft = LOF(fnum)
Do While bytesLeft
bytes = bytesLeft
If bytes > ChunkSize Then bytes = ChunkSize
ReDim tmp(1 To bytes) As Byte
Get #1, , tmp
fld.AppendChunk tmp
bytesLeft = bytesLeft - bytes
Loop
Close #fnum
End Sub
2. VB把文件從IMAGE字段中讀到文件中。
Sub loadpic(IndexNumber As Long)
Dim DcnNWind As New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
DcnNWind.CursorLocation = adUseClient
DcnNWind.Open "Provider=SQLOLEDB.1;Integrated Security=SSI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER"
rs.CursorType = adOpenKeyset
rs.LockType = adLockOptimistic
rs.Open "CustomInfo", DcnNWind, , adCmdTable
rs.Move (IndexNumber)
Call BlobToFile(rs.Fields("Image"), "c:\windows\temp\tmp.bmp", rs.Fields("Image").ActualSize)
End Sub
Private Sub BlobToFile(fld As ADODB.Field, FileName As String, Optional ChunkSize As Long )
Dim fnum As Integer, bytesLeft As Long, bytes As Long
Dim tmp() As Byte
If (fld.Attributes And adFldLong) = 0 Then
Err.Raise 1001, , "Field doesn't support the GetChunk method."
End If
If Dir$(FileName) <> "" Then Kill FileName
fnum = FreeFile
Open FileName For Binary As fnum
bytesLeft = fld.ActualSize
Do While bytesLeft
bytes = bytesLeft
If bytes > ChunkSize Then bytes = ChunkSize
tmp = fld.GetChunk(bytes)
Put #fnum, , tmp
bytesLeft = bytesLeft - bytes
Loop
Close #fnum
End Sub
Sub savepic(FileName As String, IndexNumber As Long)
Dim DcnNWind As New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
DcnNWind.CursorLocation = adUseClient
DcnNWind.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER"
rs.CursorType = adOpenKeyset
rs.LockType = adLockOptimistic
rs.Open "CustomInfo", DcnNWind, , adCmdTable
rs.Move (IndexNumber)
Call FileToBlob(rs.Fields("Image"), FileName, FileLen(FileName))
rs.UpdateBatch adAffectCurrent
End Sub
Private Sub FileToBlob(fld As ADODB.Field, FileName As String, Optional ChunkSize As Long )
Dim fnum As Integer, bytesLeft As Long, bytes As Long
Dim tmp() As Byte
If (fld.Attributes And adFldLong) = 0 Then
Err.Raise 1001, , "Field doesn't support the GetChunk method."
End If
fnum = FreeFile
Open FileName For Binary As fnum
bytesLeft = LOF(fnum)
Do While bytesLeft
bytes = bytesLeft
If bytes > ChunkSize Then bytes = ChunkSize
ReDim tmp(1 To bytes) As Byte
Get #1, , tmp
fld.AppendChunk tmp
bytesLeft = bytesLeft - bytes
Loop
Close #fnum
End Sub
2. VB把文件從IMAGE字段中讀到文件中。
Sub loadpic(IndexNumber As Long)
Dim DcnNWind As New ADODB.Connection
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
DcnNWind.CursorLocation = adUseClient
DcnNWind.Open "Provider=SQLOLEDB.1;Integrated Security=SSI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER"
rs.CursorType = adOpenKeyset
rs.LockType = adLockOptimistic
rs.Open "CustomInfo", DcnNWind, , adCmdTable
rs.Move (IndexNumber)
Call BlobToFile(rs.Fields("Image"), "c:\windows\temp\tmp.bmp", rs.Fields("Image").ActualSize)
End Sub
Private Sub BlobToFile(fld As ADODB.Field, FileName As String, Optional ChunkSize As Long )
Dim fnum As Integer, bytesLeft As Long, bytes As Long
Dim tmp() As Byte
If (fld.Attributes And adFldLong) = 0 Then
Err.Raise 1001, , "Field doesn't support the GetChunk method."
End If
If Dir$(FileName) <> "" Then Kill FileName
fnum = FreeFile
Open FileName For Binary As fnum
bytesLeft = fld.ActualSize
Do While bytesLeft
bytes = bytesLeft
If bytes > ChunkSize Then bytes = ChunkSize
tmp = fld.GetChunk(bytes)
Put #fnum, , tmp
bytesLeft = bytesLeft - bytes
Loop
Close #fnum
End Sub
Microsoft Enterprise Library 5.0
Microsoft Enterprise Library 5.0
Hands-On Labs for Microsoft Enterprise Library 5.0
---
真是後知後覺,微軟竟有此法寶;到現在才發現...
光這些 Library 就省掉好多時間開發了
上面有兩個封裝版本,就都全抓了;又要研究一翻了..
---
Microsoft Enterprise Library is a collection of reusable application blocks designed to assist software developers with common enterprise development challenges. This release includes: Caching Block, Cryptography Block, Data Access Block, Exception Handling Block, Logging Block, Policy Injection Block, Security Block, Validation Block, and Unity.
Hands-On Labs for Microsoft Enterprise Library 5.0
---
真是後知後覺,微軟竟有此法寶;到現在才發現...
光這些 Library 就省掉好多時間開發了
上面有兩個封裝版本,就都全抓了;又要研究一翻了..
---
Microsoft Enterprise Library is a collection of reusable application blocks designed to assist software developers with common enterprise development challenges. This release includes: Caching Block, Cryptography Block, Data Access Block, Exception Handling Block, Logging Block, Policy Injection Block, Security Block, Validation Block, and Unity.
2010年9月10日 星期五
OleDb方式讀取 txt、dbf、xls
[txt]
string constr=@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+vsFilePath+";Extended Properties='text;HDR=Yes;FMT=Delimited;IMEX=1;'";
OleDbDataAdapter da=new OleDbDataAdapter ();
OleDbConnection OConn=new OleDbConnection ();
OConn.ConnectionString =constr;
OConn.Open ();
OleDbCommand OCmm=new OleDbCommand ();
OCmm.CommandText ="select * from "+filename+"#txt";
OCmm.Connection=OConn;
da.SelectCommand =OCmm;
OCmm.CommandTimeout=0;
try
{
da.Fill(ds,filename);
}
catch(Exception ex)
{
throw new Exception("Error!"+ex.Message.ToString());
}
finally
{
OConn.Close();
}
[dbf]
string constr="Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB="+vsFilePath;
OdbcDataAdapter da=new OdbcDataAdapter ();
OdbcConnection OConn=new OdbcConnection ();
OConn.ConnectionString =constr;
OConn.Open ();
OdbcCommand OCmm=new OdbcCommand ();
OCmm.CommandText ="Select "+fCol+" from "+filename;
OCmm.Connection=OConn;
da.SelectCommand =OCmm;
OCmm.CommandTimeout=0;
try
{
da.Fill(ds,filename);
}
catch(Exception ex)
{
throw new Exception("Error!"+ex.Message.ToString());
}
finally
{
OConn.Close();
}
[xls]
string constr=@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+vsFilePath+newnm+";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
OleDbDataAdapter da=new OleDbDataAdapter ();
OleDbConnection OConn=new OleDbConnection ();
OConn.ConnectionString =constr;
OConn.Open ();
OleDbCommand OCmm=new OleDbCommand ();
OCmm.CommandText ="select * from [sheet1$]";
OCmm.Connection=OConn;
da.SelectCommand =OCmm;
OCmm.CommandTimeout=0;
try
{
da.Fill(ds,filename);
}
catch(Exception ex)
{
throw new Exception("Error!"+ex.Message.ToString());
}
finally
{
OConn.Close();
}
string constr=@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+vsFilePath+";Extended Properties='text;HDR=Yes;FMT=Delimited;IMEX=1;'";
OleDbDataAdapter da=new OleDbDataAdapter ();
OleDbConnection OConn=new OleDbConnection ();
OConn.ConnectionString =constr;
OConn.Open ();
OleDbCommand OCmm=new OleDbCommand ();
OCmm.CommandText ="select * from "+filename+"#txt";
OCmm.Connection=OConn;
da.SelectCommand =OCmm;
OCmm.CommandTimeout=0;
try
{
da.Fill(ds,filename);
}
catch(Exception ex)
{
throw new Exception("Error!"+ex.Message.ToString());
}
finally
{
OConn.Close();
}
[dbf]
string constr="Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB="+vsFilePath;
OdbcDataAdapter da=new OdbcDataAdapter ();
OdbcConnection OConn=new OdbcConnection ();
OConn.ConnectionString =constr;
OConn.Open ();
OdbcCommand OCmm=new OdbcCommand ();
OCmm.CommandText ="Select "+fCol+" from "+filename;
OCmm.Connection=OConn;
da.SelectCommand =OCmm;
OCmm.CommandTimeout=0;
try
{
da.Fill(ds,filename);
}
catch(Exception ex)
{
throw new Exception("Error!"+ex.Message.ToString());
}
finally
{
OConn.Close();
}
[xls]
string constr=@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+vsFilePath+newnm+";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'";
OleDbDataAdapter da=new OleDbDataAdapter ();
OleDbConnection OConn=new OleDbConnection ();
OConn.ConnectionString =constr;
OConn.Open ();
OleDbCommand OCmm=new OleDbCommand ();
OCmm.CommandText ="select * from [sheet1$]";
OCmm.Connection=OConn;
da.SelectCommand =OCmm;
OCmm.CommandTimeout=0;
try
{
da.Fill(ds,filename);
}
catch(Exception ex)
{
throw new Exception("Error!"+ex.Message.ToString());
}
finally
{
OConn.Close();
}
2010年9月8日 星期三
使用 Jet OLE DB 提供者 4.0 連線至 ISAM 資料庫
微軟官網
開啟 Excel
下列程式碼會開啟一個 Excel ISAM 資料庫:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\ExcelFile.xls;" & _
"Extended Properties=""Excel 8.0;HDR=Yes;"";"
開啟 dBASE
下列程式碼會開啟 dBASE ISAM 資料庫。 如果 dBASE 檔案 (比方說 dBaseFile.dbf) 是位於 c:\somepath,其中 C 是磁碟機,其中 somepath 是所在的資料夾 dBaseFile.dbf,如下所示:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath;" & _
"Extended Properties=DBASE III;"
在 SQL 陳述式中指定檔案名稱如下:
rst.Open "Select * From dBaseFile", cnn, , ,adCmdText
開啟 Lotus 1-2-3
下列程式碼會開啟 Lotus 1-2-3 ISAM 資料庫:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\Lotus123File.wk3;" & _
"Extended Properties=Lotus WK3;"
開啟 Paradox
下列程式碼會開啟 Paradox ISAM 資料庫。 如果 Paradox 5.0 檔案 (比方說 PdxFile.db) 是位於 c:\somepath,其中 C 是磁碟機,其中 somepath 是所在的資料夾 PdxFile.db,如下所示:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath;" & _
"Extended Properties=Paradox 5.x;"
指定 SQL 陳述式中的檔名,如下所示:
rst.Open "Select * From PdxFile", cnn, , ,adCmdText
開啟文字
如果文字檔案 (比方說 TestFile.txt) 是位於 c:\somepath,其中 C 是磁碟機,其中 somepath 是所在的資料夾 TestFile.txt,如下所示:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath;" & _
"Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
在 SQL 陳述式中指定檔案名稱如下:
rst.Open "Select * From TextFile.txt", cnn, , , adCmdText
開啟 Excel
下列程式碼會開啟一個 Excel ISAM 資料庫:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\ExcelFile.xls;" & _
"Extended Properties=""Excel 8.0;HDR=Yes;"";"
開啟 dBASE
下列程式碼會開啟 dBASE ISAM 資料庫。 如果 dBASE 檔案 (比方說 dBaseFile.dbf) 是位於 c:\somepath,其中 C 是磁碟機,其中 somepath 是所在的資料夾 dBaseFile.dbf,如下所示:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath;" & _
"Extended Properties=DBASE III;"
在 SQL 陳述式中指定檔案名稱如下:
rst.Open "Select * From dBaseFile", cnn, , ,adCmdText
開啟 Lotus 1-2-3
下列程式碼會開啟 Lotus 1-2-3 ISAM 資料庫:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath\Lotus123File.wk3;" & _
"Extended Properties=Lotus WK3;"
開啟 Paradox
下列程式碼會開啟 Paradox ISAM 資料庫。 如果 Paradox 5.0 檔案 (比方說 PdxFile.db) 是位於 c:\somepath,其中 C 是磁碟機,其中 somepath 是所在的資料夾 PdxFile.db,如下所示:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath;" & _
"Extended Properties=Paradox 5.x;"
指定 SQL 陳述式中的檔名,如下所示:
rst.Open "Select * From PdxFile", cnn, , ,adCmdText
開啟文字
如果文字檔案 (比方說 TestFile.txt) 是位於 c:\somepath,其中 C 是磁碟機,其中 somepath 是所在的資料夾 TestFile.txt,如下所示:
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=c:\somepath;" & _
"Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
在 SQL 陳述式中指定檔案名稱如下:
rst.Open "Select * From TextFile.txt", cnn, , , adCmdText
OLEDB and text files
This is a very quick example about OLEDB and read a text (.txt) file using Visual Basic 6.
The text file must be formatted as a simple CSV file with a field separator. Something like this
Test.txt
a;1;Test
b;2;Test
c;3;Test
d;4;Test
Supposing "Test.Txt" is stored in the root of the C: harddrive, the code will look like
----------------------------------------
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\;Extended Properties=""text;HDR=No;FMT=Delimited'"""
Set rs = CreateObject("ADODB.Recordset")
rs.Open "SELECT * FROM Test.txt", cn, 0, 1, 1
While Not rs.EOF
Debug.Print rs.Fields(0).Value, rs.Fields(1).Value, rs.Fields(2).Value
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
----------------------------------------
Take a look to the connection string
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\;Extended Properties=""text;HDR=No;FMT=Delimited'"""
the Data Source=c:\; is the key. If you plan to store your text file in a different folde, let's say "c:\documents and settings\Auser\Documents\myTestFiles\", you are required to change the connection string this way:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\documents and settings\Auser\Documents\myTestFiles\;Extended Properties=""text;HDR=No;FMT=Delimited'"""
The text file must be formatted as a simple CSV file with a field separator. Something like this
Test.txt
a;1;Test
b;2;Test
c;3;Test
d;4;Test
Supposing "Test.Txt" is stored in the root of the C: harddrive, the code will look like
----------------------------------------
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\;Extended Properties=""text;HDR=No;FMT=Delimited'"""
Set rs = CreateObject("ADODB.Recordset")
rs.Open "SELECT * FROM Test.txt", cn, 0, 1, 1
While Not rs.EOF
Debug.Print rs.Fields(0).Value, rs.Fields(1).Value, rs.Fields(2).Value
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
----------------------------------------
Take a look to the connection string
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\;Extended Properties=""text;HDR=No;FMT=Delimited'"""
the Data Source=c:\; is the key. If you plan to store your text file in a different folde, let's say "c:\documents and settings\Auser\Documents\myTestFiles\", you are required to change the connection string this way:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\documents and settings\Auser\Documents\myTestFiles\;Extended Properties=""text;HDR=No;FMT=Delimited'"""
2010年9月7日 星期二
在vb.net下寫多執行緒的程式
原文處
Public Class Count1
Public CountTo as Integer
' 當程序處理完畢,透過這個method來讓對方知道你已經做完了
Public event FinishedCounting(ByVal NumberOfMatches as Integer)
Sub Count()
Dim ind,tot as Integer
tot=0
For ind=1 to CountTo
tot+=1
Next ind
' raise一個事件出來說已經做完了
' 並將處理完的值回傳回去
RaiseEvent FinishedCounting(tot)
End Sub
End Class
' 這一段程式碼就是用來執行呼叫thread
Dim counter1 as new Count1()
Dim Thread1 as New System.Threading.Thread(Addressof counter1.Count)
Private Sub LetMeCallThread(Byval counter as Integer)
counter1.CountTo=counter
' 與物件之間的Call Back機制, 建立handler (Call Back的function)
' 當物件Raise該事件時,可以透過該function取得結果
AddHandler counter1.FinishedCounting,AddressOf FinishedCountingEventHandler
' 啟動執行緖
Thread1.Start()
End Sub
' 當Thread程式執行完畢(這就是所謂的CallBack機制)
Sub FinishedCountingEventHandler(ByVal Count as Integer)
msgbox(Count)
End Sub
Public Class Count1
Public CountTo as Integer
' 當程序處理完畢,透過這個method來讓對方知道你已經做完了
Public event FinishedCounting(ByVal NumberOfMatches as Integer)
Sub Count()
Dim ind,tot as Integer
tot=0
For ind=1 to CountTo
tot+=1
Next ind
' raise一個事件出來說已經做完了
' 並將處理完的值回傳回去
RaiseEvent FinishedCounting(tot)
End Sub
End Class
' 這一段程式碼就是用來執行呼叫thread
Dim counter1 as new Count1()
Dim Thread1 as New System.Threading.Thread(Addressof counter1.Count)
Private Sub LetMeCallThread(Byval counter as Integer)
counter1.CountTo=counter
' 與物件之間的Call Back機制, 建立handler (Call Back的function)
' 當物件Raise該事件時,可以透過該function取得結果
AddHandler counter1.FinishedCounting,AddressOf FinishedCountingEventHandler
' 啟動執行緖
Thread1.Start()
End Sub
' 當Thread程式執行完畢(這就是所謂的CallBack機制)
Sub FinishedCountingEventHandler(ByVal Count as Integer)
msgbox(Count)
End Sub
Microsoft Sync Framework 2.0 實作簡單的 SQL Server 資料
引用處
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data;
namespace DataSync
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
/*----- 資料同步按鈕的 Click 事件,處理資料同步 -----*/
private void btnSync_Click(object sender, EventArgs e)
{
// 定義資料庫連線
System.Data.SqlClient.SqlConnection clientConnection = new System.Data.SqlClient.SqlConnection("Server=localhost\\SQLEXPRESS;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
System.Data.SqlClient.SqlConnection serverConnection = new System.Data.SqlClient.SqlConnection("Server=SQLSERVER;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
string strMsg;
// 定義資料同步provider
SqlSyncProvider localProvider = new SqlSyncProvider("filtered_customer", clientConnection);
SqlSyncProvider remoteProvider = new SqlSyncProvider("filtered_customer", serverConnection);
// 定義資料同步協調者
Microsoft.Synchronization.SyncOrchestrator syncOrchestrator = new Microsoft.Synchronization.SyncOrchestrator();
syncOrchestrator.Direction = Microsoft.Synchronization.SyncDirectionOrder.Download; //指定只由Sever下載更新,不上傳。
syncOrchestrator.LocalProvider = localProvider;
syncOrchestrator.RemoteProvider = remoteProvider;
// 進行同步
Microsoft.Synchronization.SyncOperationStatistics syncStats;
syncStats = syncOrchestrator.Synchronize();
strMsg = "同步開始時間:";
strMsg += syncStats.SyncStartTime.ToLongTimeString().Trim();
strMsg += "\n\r";
strMsg += "同步結束時間:";
strMsg += syncStats.SyncEndTime.ToLongTimeString().Trim();
strMsg += "\n\r";
strMsg += "同步資料總筆數:";
strMsg += syncStats.UploadChangesApplied.ToString().Trim();
MessageBox.Show(strMsg);
}
/*----- 佈建Server端以及Client端必要的table & stored procedure & trigger,僅有第一次建置時需要執行-----*/
private void btnBuild_Click(object sender, EventArgs e)
{
System.Data.SqlClient.SqlConnection clientConnection = new System.Data.SqlClient.SqlConnection("Server=localhost\\SQLEXPRESS;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
System.Data.SqlClient.SqlConnection serverConnection = new System.Data.SqlClient.SqlConnection("Server=SQLSERVER;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
// 定義同步範圍與資料表
DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("filtered_customer");
DbSyncTableDescription customerDesc = SqlSyncDescriptionBuilder.GetDescriptionForTable("customer", serverConnection);
scopeDesc.Tables.Add(customerDesc);
SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning(scopeDesc);
serverConfig.ObjectSchema = "customer";
serverConfig.SetCreateTableDefault(DbSyncCreationOption.Skip);
// 將設定套用至server & client,由MSF自動佈建所需的table、trigger、SP
serverConfig.Apply(serverConnection);
serverConfig.Apply(clientConnection);
MessageBox.Show("同步環境建置完成");
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Synchronization.Data.SqlServer;
using Microsoft.Synchronization.Data;
namespace DataSync
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
/*----- 資料同步按鈕的 Click 事件,處理資料同步 -----*/
private void btnSync_Click(object sender, EventArgs e)
{
// 定義資料庫連線
System.Data.SqlClient.SqlConnection clientConnection = new System.Data.SqlClient.SqlConnection("Server=localhost\\SQLEXPRESS;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
System.Data.SqlClient.SqlConnection serverConnection = new System.Data.SqlClient.SqlConnection("Server=SQLSERVER;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
string strMsg;
// 定義資料同步provider
SqlSyncProvider localProvider = new SqlSyncProvider("filtered_customer", clientConnection);
SqlSyncProvider remoteProvider = new SqlSyncProvider("filtered_customer", serverConnection);
// 定義資料同步協調者
Microsoft.Synchronization.SyncOrchestrator syncOrchestrator = new Microsoft.Synchronization.SyncOrchestrator();
syncOrchestrator.Direction = Microsoft.Synchronization.SyncDirectionOrder.Download; //指定只由Sever下載更新,不上傳。
syncOrchestrator.LocalProvider = localProvider;
syncOrchestrator.RemoteProvider = remoteProvider;
// 進行同步
Microsoft.Synchronization.SyncOperationStatistics syncStats;
syncStats = syncOrchestrator.Synchronize();
strMsg = "同步開始時間:";
strMsg += syncStats.SyncStartTime.ToLongTimeString().Trim();
strMsg += "\n\r";
strMsg += "同步結束時間:";
strMsg += syncStats.SyncEndTime.ToLongTimeString().Trim();
strMsg += "\n\r";
strMsg += "同步資料總筆數:";
strMsg += syncStats.UploadChangesApplied.ToString().Trim();
MessageBox.Show(strMsg);
}
/*----- 佈建Server端以及Client端必要的table & stored procedure & trigger,僅有第一次建置時需要執行-----*/
private void btnBuild_Click(object sender, EventArgs e)
{
System.Data.SqlClient.SqlConnection clientConnection = new System.Data.SqlClient.SqlConnection("Server=localhost\\SQLEXPRESS;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
System.Data.SqlClient.SqlConnection serverConnection = new System.Data.SqlClient.SqlConnection("Server=SQLSERVER;Initial Catalog=pos;Persist Security Info=True;User ID=YOURID;Password=YOURPWD");
// 定義同步範圍與資料表
DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("filtered_customer");
DbSyncTableDescription customerDesc = SqlSyncDescriptionBuilder.GetDescriptionForTable("customer", serverConnection);
scopeDesc.Tables.Add(customerDesc);
SqlSyncScopeProvisioning serverConfig = new SqlSyncScopeProvisioning(scopeDesc);
serverConfig.ObjectSchema = "customer";
serverConfig.SetCreateTableDefault(DbSyncCreationOption.Skip);
// 將設定套用至server & client,由MSF自動佈建所需的table、trigger、SP
serverConfig.Apply(serverConnection);
serverConfig.Apply(clientConnection);
MessageBox.Show("同步環境建置完成");
}
}
}
2010年9月6日 星期一
不同服務器數據庫之間的數據操作
--創建鏈接服務器
exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '遠程服務器名或ip地址 '
exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用戶名 ', '密碼 '
--查詢示例
select * from ITSV.數據庫名.dbo.表名
--導入示例
select * into 表 from ITSV.數據庫名.dbo.表名
--以後不再使用時刪除鏈接服務器
exec sp_dropserver 'ITSV ', 'droplogins '
--連接遠程/局域網數據(openrowset/openquery/opendatasource)
--1、openrowset
--查詢示例
select * from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)
--生成本地表
select * into 表 from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)
--把本地表導入遠程表
insert openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)
select *from 本地表
--更新本地表
update b
set b.列A=a.列A
from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)as a inner join 本地表 b
on a.column1=b.column1
--openquery用法需要創建一個連接
--首先創建一個連接創建鏈接服務器
exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '遠程服務器名或ip地址 '
--查詢
select *
FROM openquery(ITSV, 'SELECT * FROM 數據庫.dbo.表名 ')
--把本地表導入遠程表
insert openquery(ITSV, 'SELECT * FROM 數據庫.dbo.表名 ')
select * from 本地表
--更新本地表
update b
set b.列B=a.列B
FROM openquery(ITSV, 'SELECT * FROM 數據庫.dbo.表名 ') as a
inner join 本地表 b on a.列A=b.列A
--3、opendatasource/openrowset
SELECT *
FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陸名;Password=密碼 ' ).test.dbo.roy_ta
--把本地表導入遠程表
insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陸名;Password=密碼 ').數據庫.dbo.表名
select * from 本地表
然後進行判斷,判斷的時候帶上機器名,數據庫名,用戶名,表名
例如:
if exists(select 1 from servername1.dbname1.dbo.tbname1 where ...)
insert into ...
else
update ....
exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '遠程服務器名或ip地址 '
exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用戶名 ', '密碼 '
--查詢示例
select * from ITSV.數據庫名.dbo.表名
--導入示例
select * into 表 from ITSV.數據庫名.dbo.表名
--以後不再使用時刪除鏈接服務器
exec sp_dropserver 'ITSV ', 'droplogins '
--連接遠程/局域網數據(openrowset/openquery/opendatasource)
--1、openrowset
--查詢示例
select * from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)
--生成本地表
select * into 表 from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)
--把本地表導入遠程表
insert openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)
select *from 本地表
--更新本地表
update b
set b.列A=a.列A
from openrowset( 'SQLOLEDB ', 'sql服務器名 '; '用戶名 '; '密碼 ',數據庫名.dbo.表名)as a inner join 本地表 b
on a.column1=b.column1
--openquery用法需要創建一個連接
--首先創建一個連接創建鏈接服務器
exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '遠程服務器名或ip地址 '
--查詢
select *
FROM openquery(ITSV, 'SELECT * FROM 數據庫.dbo.表名 ')
--把本地表導入遠程表
insert openquery(ITSV, 'SELECT * FROM 數據庫.dbo.表名 ')
select * from 本地表
--更新本地表
update b
set b.列B=a.列B
FROM openquery(ITSV, 'SELECT * FROM 數據庫.dbo.表名 ') as a
inner join 本地表 b on a.列A=b.列A
--3、opendatasource/openrowset
SELECT *
FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陸名;Password=密碼 ' ).test.dbo.roy_ta
--把本地表導入遠程表
insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陸名;Password=密碼 ').數據庫.dbo.表名
select * from 本地表
然後進行判斷,判斷的時候帶上機器名,數據庫名,用戶名,表名
例如:
if exists(select 1 from servername1.dbname1.dbo.tbname1 where ...)
insert into ...
else
update ....
使用OPENROWSET把大型檔讀取到SQL Server
引用處
BULK選項被增加到SQL Server 2005中的T-SQL中,它也能夠在SQL Server 2008中使用。當使用SQL Server 2000時,使用sp_OA_Create和sp_OA_Method擴展存儲過程來讀和寫到檔系統中是可能的。XPs還是能夠使用的,但是默認情況下因為安全緣故所以不能使用,當它們可用時,使用更多的安全性能比如OPENROWSET是一個更好的嘗試。
當使用BULK提供者關鍵字時,你可以命名一個資料檔來讀取下面三種類型對象之一:
SINGLE_BLOB,用二進位讀取一個文件(最大值)
SINGLE_CLOB,用varchar讀取一個文件(最大值)
SINGLE_NCLOB,用nvarchar讀取一個文件(最大值)
OPENROWSET返回一個單獨的欄位,命名為BulkColumn,正如它的結果一樣。下面是一個讀取文字檔案的例子。
SELECT BulkColumn FROM OPENROWSET (BULK 'c:\temp\mytxtfile.txt', SINGLE_CLOB) MyFile
這個關係名,在本例中是MyFile,是由OPENROWSET要求的。
當讀取也必須被發現的單行時,還必須遵守如下所示的要求。
訪問控制一直是備受關注的一個問題。讀取檔的作業系統級別檔的操作是在SQL Server資料引擎使用的帳戶許可權下執行的。因此,只有可以訪問該帳戶的檔才能夠讀取。這包括了網路驅動器或者UNC路徑,如果這個帳號具有該許可權那麼這些是允許的。如果你想讀取網路驅動器,那麼用域用戶來運行SQL Server。
BULK提供者不能在Unicode和普通的ASCII檔之間轉換。它可能會告訴你在檔中使用哪種類型的編碼。如果你沒有,那麼這個結果將會是錯誤4806,可以在下面看到:
SELECT BulkColumn FROM OPENROWSET (BULK 'c:\temp\SampleUnicode.txt', SINGLE_CLOB) MyFile
Msg 4806, Level 16, State 1, Line 1
SINGLE_CLOB requires a double-byte character set (DBCS) (char) input file. The file specified is Unicode.
Unicode文件必須用下麵顯示的SINGLE_NCLOB選項讀取:
SELECT BulkColumn
FROM OPENROWSET (BULK 'c:\temp\SampleUnicode.txt', SINGLE_NCLOB) MyFile
類似的是,非文本結構的檔比如Word檔是不能轉化的。在讀取或者作為具有SINGLE_BLOB選項的二進位檔來讀取時,它們必須通過其他的機制來轉化。
當涉及你提供檔的名稱時,OPENROWSET就會顯得不那麼靈活。它必須是一個字串常數。當事先不知道檔案名時,這個要求促進了動態SQL的使用。
下面是一個存儲過程,它可以讀取任何文字檔案並返回一個作為輸出變數的內容:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[ns_txt_file_read]
@os_file_name NVARCHAR(256)
,@text_file VARCHAR(MAX) OUTPUT
/* Reads a text file into @text_file
*
* Transactions: may be in a transaction but is not affected
* by the transaction.
*
* Error Handling: Errors are not trapped and are thrown to
* the caller.
*
* Example:
declare @t varchar(max)
exec ns_txt_file_read 'c:\temp\SampleTextDoc.txt', @t output
select @t as [SampleTextDoc.txt]
*
* History:
* WHEN WHO WHAT
* ---------- ---------- ---------------------------------------
* 2007-02-06 anovick Initial coding
**************************************************************/
AS
DECLARE @sql NVARCHAR(MAX)
, @parmsdeclare NVARCHAR(4000)
SET NOCOUNT ON
SET @sql = 'select @text_file=(select * from openrowset (
bulk ''' + @os_file_name + '''
,SINGLE_CLOB) x
)'
SET @parmsdeclare = '@text_file varchar(max) OUTPUT'
EXEC sp_executesql @stmt = @sql
, @params = @parmsdeclare
, @text_file = @text_file OUTPUT
要看看它是如何實現的,只需執行示例腳本:首先創建一個叫做"SampleTextDoc.txt"的文字檔案並把一些文本資料添加到該文件中。在我們的例子中,我們增加了下面的文本"The quick brown fox jumped over the lazy dog."。
DECLARE @t VARCHAR(MAX)
EXEC ns_txt_file_read 'c:\temp\SampleTextDoc.txt', @t output
SELECT @t AS [SampleTextDoc.txt]
結果是:
SampleTextDoc.txt
The quick brown fox jumped over the lazy dog.
(1 row(s) affected)
讀取文字檔案的性能顯著加快了,這是因為這些檔是按順序讀取的。在一個開發機器中使用一個64 bit SQL Server 2008讀取一個750,000,000位元組的文件只需要7秒。
BULK選項被增加到SQL Server 2005中的T-SQL中,它也能夠在SQL Server 2008中使用。當使用SQL Server 2000時,使用sp_OA_Create和sp_OA_Method擴展存儲過程來讀和寫到檔系統中是可能的。XPs還是能夠使用的,但是默認情況下因為安全緣故所以不能使用,當它們可用時,使用更多的安全性能比如OPENROWSET是一個更好的嘗試。
當使用BULK提供者關鍵字時,你可以命名一個資料檔來讀取下面三種類型對象之一:
SINGLE_BLOB,用二進位讀取一個文件(最大值)
SINGLE_CLOB,用varchar讀取一個文件(最大值)
SINGLE_NCLOB,用nvarchar讀取一個文件(最大值)
OPENROWSET返回一個單獨的欄位,命名為BulkColumn,正如它的結果一樣。下面是一個讀取文字檔案的例子。
SELECT BulkColumn FROM OPENROWSET (BULK 'c:\temp\mytxtfile.txt', SINGLE_CLOB) MyFile
這個關係名,在本例中是MyFile,是由OPENROWSET要求的。
當讀取也必須被發現的單行時,還必須遵守如下所示的要求。
訪問控制一直是備受關注的一個問題。讀取檔的作業系統級別檔的操作是在SQL Server資料引擎使用的帳戶許可權下執行的。因此,只有可以訪問該帳戶的檔才能夠讀取。這包括了網路驅動器或者UNC路徑,如果這個帳號具有該許可權那麼這些是允許的。如果你想讀取網路驅動器,那麼用域用戶來運行SQL Server。
BULK提供者不能在Unicode和普通的ASCII檔之間轉換。它可能會告訴你在檔中使用哪種類型的編碼。如果你沒有,那麼這個結果將會是錯誤4806,可以在下面看到:
SELECT BulkColumn FROM OPENROWSET (BULK 'c:\temp\SampleUnicode.txt', SINGLE_CLOB) MyFile
Msg 4806, Level 16, State 1, Line 1
SINGLE_CLOB requires a double-byte character set (DBCS) (char) input file. The file specified is Unicode.
Unicode文件必須用下麵顯示的SINGLE_NCLOB選項讀取:
SELECT BulkColumn
FROM OPENROWSET (BULK 'c:\temp\SampleUnicode.txt', SINGLE_NCLOB) MyFile
類似的是,非文本結構的檔比如Word檔是不能轉化的。在讀取或者作為具有SINGLE_BLOB選項的二進位檔來讀取時,它們必須通過其他的機制來轉化。
當涉及你提供檔的名稱時,OPENROWSET就會顯得不那麼靈活。它必須是一個字串常數。當事先不知道檔案名時,這個要求促進了動態SQL的使用。
下面是一個存儲過程,它可以讀取任何文字檔案並返回一個作為輸出變數的內容:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[ns_txt_file_read]
@os_file_name NVARCHAR(256)
,@text_file VARCHAR(MAX) OUTPUT
/* Reads a text file into @text_file
*
* Transactions: may be in a transaction but is not affected
* by the transaction.
*
* Error Handling: Errors are not trapped and are thrown to
* the caller.
*
* Example:
declare @t varchar(max)
exec ns_txt_file_read 'c:\temp\SampleTextDoc.txt', @t output
select @t as [SampleTextDoc.txt]
*
* History:
* WHEN WHO WHAT
* ---------- ---------- ---------------------------------------
* 2007-02-06 anovick Initial coding
**************************************************************/
AS
DECLARE @sql NVARCHAR(MAX)
, @parmsdeclare NVARCHAR(4000)
SET NOCOUNT ON
SET @sql = 'select @text_file=(select * from openrowset (
bulk ''' + @os_file_name + '''
,SINGLE_CLOB) x
)'
SET @parmsdeclare = '@text_file varchar(max) OUTPUT'
EXEC sp_executesql @stmt = @sql
, @params = @parmsdeclare
, @text_file = @text_file OUTPUT
要看看它是如何實現的,只需執行示例腳本:首先創建一個叫做"SampleTextDoc.txt"的文字檔案並把一些文本資料添加到該文件中。在我們的例子中,我們增加了下面的文本"The quick brown fox jumped over the lazy dog."。
DECLARE @t VARCHAR(MAX)
EXEC ns_txt_file_read 'c:\temp\SampleTextDoc.txt', @t output
SELECT @t AS [SampleTextDoc.txt]
結果是:
SampleTextDoc.txt
The quick brown fox jumped over the lazy dog.
(1 row(s) affected)
讀取文字檔案的性能顯著加快了,這是因為這些檔是按順序讀取的。在一個開發機器中使用一個64 bit SQL Server 2008讀取一個750,000,000位元組的文件只需要7秒。
訂閱:
文章 (Atom)