1

別の接続が開かれ、トランザクションが実行されている間に、クエリを実行する関数を呼び出す必要があります。

わかりました、これは奇妙です。ここにいくつかのコードがあります:

主要部分:

Using connection As New SqlConnection(connectionString)
    connection.Open()
    Dim command As SqlCommand = connection.CreateCommand()
    Dim transaction As SqlTransaction
    transaction = connection.BeginTransaction("myTransaction")
    command.Connection = connection
    command.Transaction = transaction
    command.CommandText = sSQL
    Try
        command.ExecuteNonQuery()
        Dim functionResult As String = myFunction(param1, param2)
        If functionResult <> "" Then
            'error! i need to rollback the first query done here!
            transaction.Rollback()
        else
            transaction.Commit()
        End If
    Catch ex As Exception
        transaction.Rollback()
    End Try
    End If
End Using

myFunctionは多くのことを行い、多くのクエリを実行します。すべてのクエリは(今回はトランザクションなしで)接続を再開する必要がありますが、関数内で最初のクエリを実行しようとするたびに、データベースからタイムアウトエラーが発生しました(30秒後)。

既に開いている接続内のすべての myFunction コードを「コピーして貼り付け」、既に開いている接続を使用して、この作業を実行できることはわかっていますが、その関数を複数回使用しているため、コードを台無しにしたくありません。

どうすればこれを解決できますか?

詳細については編集してください:これは私が使用しているコードの縮小版ですが、ここでは「myFunction」の機能の縮小版です:

Dim connectionString As String = "my connection string"
Dim queryString As String = "SELECT id FROM foo WHERE param1 = @myValue"
Dim ds As DataSet = New DataSet()
Try
    Using connection As New SqlConnection(connectionString)
        Dim command As New SqlCommand(queryString, connection)
        connection.Open()
        command.CommandText = queryString
        command.Parameters.Add("@myValue", SqlDbType.Int).Value = 10
        Dim adapter As New SqlDataAdapter()
        adapter.SelectCommand = command
        adapter.Fill(ds, "randomName")
        If ds.Tables("randomName").Rows.Count < 0 Then
            'error!
            connection.Close()
            Return "error"
        End If
    End Using
Catch ex As Exception
    Return "Database error - " & ex.Message
End Try

コマンドのコード実行 (デバッグ中でも)adapter.Fill(ds, "randomName")が 30 秒間フリーズし、その後、タイムアウト エラーが発生します。

4

1 に答える 1

3

接続はいくつでも使用できますが、相互に干渉しないようにしてください。SQL サーバーはデータの整合性を維持することに非常に注意を払っているため、コミットされていないトランザクションがコミットされていない別のトランザクションと競合すると、デッドロックが発生します。

トランザクション分離レベルで遊んでみたいと思うかもしれません。SQL サーバーのデフォルトは READ COMMITTED です。READ UNCOMMITTED に設定してみてください。ドキュメントを読んで、結果を認識してください。

上記のリンクから:

SQL Server では、次のいずれかを使用して、コミットされていないデータ変更のダーティ リードからトランザクションを保護しながら、ロックの競合を最小限に抑えることもできます。

  • READ_COMMITTED_SNAPSHOT データベース オプションが ON に設定された READ COMMITTED 分離レベル。
  • SNAPSHOT 分離レベル。
于 2013-11-05T14:59:38.417 に答える