避免使用事务

时间:2016-09-21 22:26:50

标签: sql-server vb.net tsql

我有几个插入查询,它们被合并到事务范围中。第一个插入是创建新产品文章编号,该编号是通过将表格中的最高位增加一个来构建的。不幸的是,我刚刚注意到,在测试期间,如果例如来自两个不同应用程序的两个用户点击按钮触发我的交易方法,他们可以获得相同的新产品编号并插入它。我该如何避免这种情况?

以下部分交易查询:

Public Sub ProcessArticle(ByRef artikel As ArticlesVariations)
        Dim strcon = New AppSettingsReader().GetValue("ConnectionString", GetType(System.String)).ToString()
        Using connection As New SqlConnection(strcon)
            connection.Open()
            Using transaction = connection.BeginTransaction()
                Try

                            Using cmd As New SqlCommand("INSERT INTO tbArtikel (Nummer) VALUES (@Nummer);Select Scope_Identity()", transaction.Connection)
                                cmd.CommandType = CommandType.Text
                                cmd.Connection = connection
                                cmd.Transaction = transaction

                                 'Get next product number from table tbArtikel  (this will be new product number)'
                                 Dim NewArtNummer as String =  New DALArtikel().GetNewArtikelNumber(transaction)
                                 art.Nummer = NewArtNummer

                                cmd.Parameters.AddWithValue("@Nummer", art.Nummer)
'Get inserted product id for other diffrent inserts below'
 newArticleRowId = CInt(cmd.ExecuteScalar()) 

'....
other INSERTs queries to other tables ...
...'

       transaction.Commit()
                Catch ex As Exception
                    transaction.Rollback()
                    Throw 'Rethrow exception.'
                End Try
            End Using
        End Using
    End Sub

文章编号是varchar列(我知道它不好等),但它是如何在当前范围内实现的,无法更改它。

请注意,我无法对数据库级别进行任何更改,例如新表,触发器等(一个例外是在数字列上创建唯一索引)。我必须从应用程序级别实现这一点。

我有三个选择,并愿意接受您的建议:

第一个选项:

a)将此列设为唯一列,这样当只插入一个的几个用户将插入该数字但所有其他用户将从catch获取有关唯一键违规的错误,因此我可以以某种方式管理它让信息再次重试。

b)与a)相同,但隔离级别设置为ReadUncommited - 从我的角度来看,这将使我在下次用户阅读newnumber时有机会从脏数字中读取(所以也是从第一个用户插入)所以他们有机会获得下一个号码。

第二个选项:

只是将事务隔离设置为Read uncommitted - 但这并不能保证所有相同的线路用户都会获得新的数字(可能最糟糕的是)

第3个选项:

听说有关TABLOCK的事情,但不知道在这种情况下是否可以考虑。

......别的什么?

目前我正在考虑使用第一个选项-catch错误并告知用户。

1 个答案:

答案 0 :(得分:0)

我跟着你的一些旧问题......这显然不是那么容易解决的问题。因此,我有一个完全不同的想法:

由于您的ProductNumber是VARCHAR,您可以在那里写任何内容吗?

是否可以在插入时将GETDATE()设置为此字符串文字(ISO 8601)并稍后执行UPDATE语句,这会将值重新设置为正确的编号按插入顺序?

无论如何,奇怪而丑陋......