none
資料庫交易的鎖定方式無法改成snapshot RRS feed

  • 問題

  • *****電腦作業環境*****
    開發工具:Visual Studio 2010 Pro
    .NET版本:4.0
    開發類型:Windows Form
    作業系統:Win 7 pro 32 bit SP1
    資料庫:MS SQL 2008 R2

    各位前輩們好

    由於在VB6系統程式碼裡面用的是adLockOptimistic ,指示以樂觀鎖定方式處理。

    我在改寫成NET時先嘗試資料庫交易鎖定,想將鎖定型態更改成Snapshot(樂觀鎖定)

    但是程式一直跳出例外:無法支援隔離層次或使之增強

    但是鎖定型態用Serializable卻可以通過,想請前輩們指點迷津

    參考文章:

    IsolationLevel 列舉型別

    [SQL Server] 鎖定使用的藝術 (Part 1) - 鎖定控制類型

    [SQL Server] 鎖定使用的藝術 (Part 2) - 隔離層次 (Isolation Level)

    中文命名是公司要求,以下是測試的程式碼

    Using 交易連線 As New OleDb.OleDbConnection("連線字串") 讀取程序("Select * from 傳票表 where 1=2") ' BeginTrans 傳票表配接器.SelectCommand.Connection = 交易連線 交易連線.Open()

    ' 此行程式跳出例外 傳票表配接器.SelectCommand.Transaction = 交易連線.BeginTransaction(IsolationLevel.Snapshot)

    Dim 新資料列 As DataRow = Nothing Try 新資料列 = 資料集.Tables("傳票表").NewRow() 新資料列("日期") = v日期 新資料列("序號") = v序號 新資料列("科目代號") = v科目代號 新資料列("會計科目") = v會計科目 新資料列("摘要") = v摘要 新資料列("金額") = v金額 新資料列("已過帳") = "" 新資料列("列印順序") = v順序 資料集.Tables("傳票表").Rows.Add(新資料列) 傳票表指令.GetInsertCommand(傳票表配接器.Update(資料集, "傳票表")) 傳票表配接器.SelectCommand.Transaction.Commit() Catch ex As Exception 傳票表配接器.SelectCommand.Transaction.Rollback() MsgBox("出現錯誤..." & vbNewLine & ex.Message, MsgBoxStyle.Critical, "提示") End Try End Using


    讀取資料表的副程式

        Private Sub 讀取程序(ByVal vSQL As String, Optional ByVal v資料表名稱 As String = Nothing)
            If v資料表名稱 = Nothing Then
                Dim v分割() As String = vSQL.Split(" ") ' 沒指定v資料表名稱 程式自動擷取字串
                v資料表名稱 = v分割(Array.IndexOf(v分割, "from") + 1)
            End If
            If IsNothing(資料集.Tables(v資料表名稱)) = False Then 資料集.Tables(v資料表名稱).Clear()
            Select Case v資料表名稱
                Case "傳票表"
                    傳票表配接器.SelectCommand = New OleDb.OleDbCommand(vSQL, SQL連線)
                    傳票表配接器.Fill(資料集, v資料表名稱)
                Case Else
                    資料表配接器.SelectCommand = New OleDb.OleDbCommand(vSQL, SQL連線)
                    資料表配接器.Fill(資料集, v資料表名稱)
            End Select
        End Sub

    2013年12月19日 上午 01:24

解答

所有回覆

  • 您好,
    您要使用「System.Data.SqlClient.SqlConnection」!

    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/


    • 已編輯 亂馬客 2013年12月19日 上午 01:52
    • 已標示為解答 GISK 2013年12月19日 上午 05:27
    2013年12月19日 上午 01:52
  • 亂馬客 您好

    所以是Oledb不能支援Snapshot鎖定嗎?

    2013年12月19日 上午 02:11
  • OLE DB 無法直接支援,可參考:

    http://stackoverflow.com/questions/9726958/neither-the-isolation-level-nor-a-strengthening-of-it-is-supported


    強力監督SQL Injection問題!!

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    • 已標示為解答 GISK 2013年12月19日 上午 05:27
    2013年12月19日 上午 03:02
    版主
  • 嗯!

    是的! 一定要用  System.Data.SqlClient


    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2013年12月19日 上午 03:42
  • 小朱版主 您好

    我不知道該怎麼在程式開始時就將此段命令設置給SQL

    SET TRANSACTION ISOLATION LEVEL SNAPSHOT;

    懇請指點

    另外,有3個重要資料表在程式執行過程要同時實行BeginTrans

    我將這3個資料表都指向同一個連線「交易連線」去處理Select、Update、Insert、Delete

    其他只做Select的指向「SQL連線」

        Dim SQL連線 As New OleDb.OleDbConnection(連線字串)
        Dim 交易連線 As New OleDb.OleDbConnection(連線字串 & ";Pooling=false")

    再將交易連線的BeginTransaction指向Transaction物件

    Dim 資料庫交易 As OleDb.OleDbTransaction
    資料庫交易 = 交易連線.BeginTransaction
    
    傳票表配接器.SelectCommand.Transaction = 資料庫交易
    資料表1TableAdapter.Transaction = 資料庫交易
    資料表2TableAdapter.Transaction = 資料庫交易

    最後資料處理完成再實行

    資料庫交易.Commit() '(在別的處理程序,不在宣告開始BeginTrans的程序裡)

    目的是要資料確認沒有錯誤後再寫入3個重要資料表

    我的認知是這樣做可以確保資料沒有錯誤

    請問這樣的寫法是OK的嗎?有沒有什麼地方應該注意呢?

    2013年12月19日 上午 03:54
  • 亂馬客 您好

    謝謝您,我再試試看有沒有辦法在Serializable鎖定下完成需要的處理工作

    目前是知道在Select陳述式加入 With (NOLOCK) 可以取到資料

    2013年12月19日 上午 04:02
  • 您可以在呼叫BeginTransaction時傳入IsolationLevel.Snapshot當做參數

    另外這樣的寫好應該沒有問題

    • 已標示為解答 GISK 2013年12月19日 上午 05:27
    2013年12月19日 上午 04:04
  • tihs 您好

    公司指示用OLEDB方式連接,亂馬客 與 小朱版主 說明OLEDB無法直接支援SnapShot鎖定

    所以我發問文章的「交易連線.BeginTransaction(IsolationLevel.Snapshot)」就無法使用了

    如果我的想法沒問題,那就朝著這方面去實作測試與編寫程式

    謝謝您的回覆

    2013年12月19日 上午 05:27