简体   繁体   中英

Transactions in vb.net locks table and SELECT gets timeout

I have the following problem: Inside one sqltransaction in vb.net I INSERT data into several tables.
it is something like this:

...
sqltransaction = connection.begintransaction
INSERT into table1
...
for i=1 to x
    ...
    INSERT into table2
    ...
    SELECT FROM table3
    ...
    INSERT into table3
    ...
next i
sqltransaction.commit
...

Private Sub salveazaCerereaDeOferta()
    If checkCompletion() = 1 Then
        Dim conn As New SqlConnection(My.Settings.GestiuneService2012_beSQLConnectionString)
        conn.Open()
        Dim sqlTrans As SqlTransaction = conn.BeginTransaction()
        Try
            Dim cmdInsertCerereOferta As SqlCommand = conn.CreateCommand
            cmdInsertCerereOferta.Transaction = sqlTrans
            cmdInsertCerereOferta.CommandText = "INSERT INTO ListaCereriOferte (IDFurnizor,NrCerereOferta,DataCerereOferta,IDModTransCerereOferta,ObservatiiCerereOferta)" + _
                                                " VALUES (@IDFurnizor,@NrCerereOferta,@DataCerereOferta,@IDModTransCerereOferta,@ObservatiiCerereOferta);" + _
                                                " SELECT SCOPE_IDENTITY();"
            cmdInsertCerereOferta.Parameters.Add("@IDFurnizor", SqlDbType.Int).Value = CInt(Me.t_IDFurnizor.Text)
            cmdInsertCerereOferta.Parameters.Add("@NrCerereOferta", SqlDbType.Int).Value = CInt(Me.t_NumarCerereOferta.Text)
            cmdInsertCerereOferta.Parameters.Add("@DataCerereOferta", SqlDbType.Date).Value = CDate(Me.t_DataCerereOferta.Text)
            cmdInsertCerereOferta.Parameters.Add("@IDModTransCerereOferta", SqlDbType.Int).Value = 1
            cmdInsertCerereOferta.Parameters.Add("@ObservatiiCerereOferta", SqlDbType.NVarChar).Value = Me.t_ObservatiiCerereOferta.Text
            Dim IDCerereOferta As Integer = cmdInsertCerereOferta.ExecuteScalar
            Dim ListaPieseCerereOferta = Me.CerereOfertaDataSet.ListaPieseCerereOferta.AsEnumerable
            Dim ListaNecesarePePiesa = Me.CerereOfertaDataSet.NecesarePeOferta.AsEnumerable
            Dim PieseOferta = From q In ListaPieseCerereOferta _
                                 Select q
            Dim cantTotalaPiese = Aggregate q In ListaPieseCerereOferta _
                                   Into Sum(q.Cantitate)
            Dim salvat As Integer = 0
            Dim curIDPiesaDeSchimb As Integer
            For Each piesa In PieseOferta
                curIDPiesaDeSchimb = piesa.IDPiesaDeSchimb
                Dim NecesarePePiesa = From p In ListaNecesarePePiesa _
                                      Select p _
                                      Order By p.IDNecesar Descending
                Dim curIDNecesar As Integer
                For Each necesar In NecesarePePiesa
                    curIDNecesar = necesar.IDNecesar
                    Dim cmdInsertPiesaCerereOferta As SqlCommand = conn.CreateCommand
                    cmdInsertPiesaCerereOferta.Transaction = sqlTrans
                    cmdInsertPiesaCerereOferta.CommandText = "INSERT INTO CereriOferte (IDCerereOferta,IDPiesaDeSchimb,Cantitate,UM,Observatii)" + _
                                                                " VALUES (@IDCerereOferta,@IDPiesaDeSchimb,@Cantitate,@UM,@Observatii);" + _
                                                                " SELECT SCOPE_IDENTITY();"
                    cmdInsertPiesaCerereOferta.Parameters.Add("@IDCerereOferta", SqlDbType.Int)
                    cmdInsertPiesaCerereOferta.Parameters.Add("@IDPiesaDeSchimb", SqlDbType.Int)
                    cmdInsertPiesaCerereOferta.Parameters.Add("@Cantitate", SqlDbType.Float)
                    cmdInsertPiesaCerereOferta.Parameters.Add("@UM", SqlDbType.NVarChar)
                    cmdInsertPiesaCerereOferta.Parameters.Add("@Observatii", SqlDbType.NVarChar)
                    Dim cmdInsertNecesarCerereOferta As SqlCommand = conn.CreateCommand
                    cmdInsertNecesarCerereOferta.Transaction = sqlTrans
                    cmdInsertNecesarCerereOferta.CommandText = "INSERT INTO NecesareCereriOferte (IDPiesaNecesar,IDPiesaCerereOferta)" + _
                                                               " VALUES (@IDPiesaNecesar,@IDPiesaCerereOferta)"
                    cmdInsertNecesarCerereOferta.Parameters.Add("@IDPiesaNecesar", SqlDbType.Int)
                    cmdInsertNecesarCerereOferta.Parameters.Add("@IDPiesaCerereOferta", SqlDbType.Int)
                    Select Case curIDNecesar
                        Case 0
                            cmdInsertPiesaCerereOferta.Parameters("@IDCerereOferta").Value = IDCerereOferta
                            cmdInsertPiesaCerereOferta.Parameters("@IDPiesaDeSchimb").Value = curIDPiesaDeSchimb
                            cmdInsertPiesaCerereOferta.Parameters("@Cantitate").Value = 1
                            cmdInsertPiesaCerereOferta.Parameters("@UM").Value = piesa.UM
                            cmdInsertPiesaCerereOferta.Parameters("@Observatii").Value = ""
                            For i = 1 To necesar.Cantitate
                                cmdInsertPiesaCerereOferta.ExecuteNonQuery()
                                salvat += 1
                                Me.tsspb_SalvareCerereOferta.Value = CInt(100 * salvat / cantTotalaPiese)
                            Next
                        Case Is > 0
                            Me.PieseNecesarePeOfertaTableAdapter.Fill(Me.CerereOfertaDataSet.PieseNecesarePeOferta, curIDNecesar, curIDPiesaDeSchimb, CInt(necesar.Cantitate))
                            Dim ListaPieseNecesarePeOferta = Me.CerereOfertaDataSet.PieseNecesarePeOferta.AsEnumerable
                            Dim PieseNecesareOferta = From q In ListaPieseNecesarePeOferta _
                                                 Select q
                            For i = 1 To necesar.Cantitate
                                cmdInsertPiesaCerereOferta.Parameters("@IDCerereOferta").Value = IDCerereOferta
                                cmdInsertPiesaCerereOferta.Parameters("@IDPiesaDeSchimb").Value = curIDPiesaDeSchimb
                                cmdInsertPiesaCerereOferta.Parameters("@Cantitate").Value = 1
                                cmdInsertPiesaCerereOferta.Parameters("@UM").Value = piesa.UM
                                cmdInsertPiesaCerereOferta.Parameters("@Observatii").Value = ""
                                Dim insertedIDPiesaCerereOferta As Integer = cmdInsertPiesaCerereOferta.ExecuteScalar
                                cmdInsertNecesarCerereOferta.Parameters("@IDPiesaNecesar").Value = PieseNecesareOferta(i - 1).IDPiesaNecesar
                                cmdInsertNecesarCerereOferta.Parameters("@IDPiesaCerereOferta").Value = insertedIDPiesaCerereOferta
                                cmdInsertNecesarCerereOferta.ExecuteNonQuery()
                                salvat += 1
                                Me.tsspb_SalvareCerereOferta.Value = CInt(100 * salvat / cantTotalaPiese)
                            Next
                    End Select
                Next
            Next
            sqlTrans.Commit()
            MsgBox("Cererea de oferta a fost salvata.")
        Catch ex As Exception
            Try
                sqlTrans.Rollback()
                MsgBox("A aparut o eroare." + vbNewLine + ex.ToString + vbNewLine + "RollBack success. Cererea nu a fost salvata.")
            Catch ex2 As SqlException
                If Not sqlTrans.Connection Is Nothing Then
                    MsgBox("An exception of type " & ex2.GetType().ToString() & _
                                      " was encountered while attempting to roll back the transaction.")
                End If
            End Try
        Finally
            If conn.State = ConnectionState.Open Then conn.Close()
        End Try
    Else
        MsgBox("Nu ai completat integral cererea de oferta!")
    End If
End Sub

query that locks:

SELECT     TOP (100) PERCENT dbo.qry_NecesareNerezolvate.IDPiesaNecesar, COUNT(dbo.NecesareCereriOferte.IDPiesaCerereOferta) AS CereriOferte, 
                      dbo.qry_NecesareNerezolvate.IDNecesar, dbo.qry_NecesareNerezolvate.IDPiesaDeSchimb, dbo.qry_NecesareNerezolvate.Cantitate
FROM         dbo.qry_NecesareNerezolvate LEFT OUTER JOIN
                      dbo.NecesareCereriOferte ON dbo.qry_NecesareNerezolvate.IDPiesaNecesar = dbo.NecesareCereriOferte.IDPiesaNecesar
GROUP BY dbo.qry_NecesareNerezolvate.IDPiesaNecesar, dbo.qry_NecesareNerezolvate.IDNecesar, dbo.qry_NecesareNerezolvate.IDPiesaDeSchimb, 
                      dbo.qry_NecesareNerezolvate.Cantitate

qry_NecesareNerezolvate:

SELECT     TOP (100) PERCENT dbo.Necesare.IDPiesaNecesar, dbo.Necesare.IDNecesar, dbo.Necesare.IDPiesaDeSchimb, dbo.Necesare.Cantitate, dbo.Necesare.UM, 
                  dbo.Necesare.Observatii
FROM         dbo.Necesare LEFT OUTER JOIN
                  dbo.qry_NecesareComandateRezolvate ON dbo.Necesare.IDPiesaNecesar =     dbo.qry_NecesareComandateRezolvate.IDPiesaNecesar
WHERE     (dbo.qry_NecesareComandateRezolvate.IDPiesaNecesar IS NULL)

qry_NecesareComandateRezolvate:

SELECT     dbo.Necesare.IDPiesaNecesar, dbo.NecesareComenzi.IDPiesaComanda, dbo.NecesareRezolvate.IDBonTransfer
FROM         dbo.Necesare LEFT OUTER JOIN
                  dbo.NecesareComenzi ON dbo.Necesare.IDPiesaNecesar = dbo.NecesareComenzi.IDPiesaNecesar LEFT OUTER JOIN
                  dbo.NecesareRezolvate ON dbo.Necesare.IDPiesaNecesar = dbo.NecesareRezolvate.IDPiesaNecesar
WHERE     (dbo.NecesareComenzi.IDPiesaComanda IS NOT NULL) OR
                  (dbo.NecesareRezolvate.IDBonTransfer IS NOT NULL)

for i=1 : insert , select then insert is working
then i=2 and: INSERT into table2... is working but SELECT FROM table1 and table3... gets timeout...

I don't understand why!
PS: If I break the code before second run of SELECT FROM table3 then go to SSMS and run the select query it gets timeout too...

In your code sample below, you have the transaction open till the end of the For Loop. It seems to me that when i =1 , the transaction gets opened and a insertion is made. Now when i=2 , the to be inserted row when i=1 is in uncomitted state and if your select is joining to the table1 the lock level would have escalated to table level and locked everything down. Move the commit to inside the for loop and check how it goes.

for i=1 to x
    ...
    INSERT into table2
    ...
    SELECT FROM table3
    ...
    INSERT into table3
    ...
next i
sqltransaction.commit

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM