我有几个插入查询,它们在事务中合并。第一个插入是创建新产品的articel数字,在表格中增加最多。不幸的是,我只是注意到mostly
在测试期间,如果例如来自两个不同应用程序的两个用户点击按钮触发我的交易的方法他们可以获得相同的新产品编号。如何避免这种情况?是否有像第一次插入时锁定的东西,以便如果第一个用户访问要插入的表限制其他用户的插入,那么他们必须在第一次用户插入完成后在队列中等待?有类似的东西吗?此外我想如果有人插入其他用户无法插入。我用你要理解的代码做了评论。
以下部分交易查询:
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
For Each kvp As KeyValuePair(Of Integer, Artikel) In artikel.collection
articleIndex = kvp.Key
Dim art As Artikel = kvp.Value
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
答案 0 :(得分:2)
确保用户未分配相同值的唯一方法是在插入行时从服务器发出这些值。这是服务器为PK发布AI值的全部前提。
但是因为你的东西是一个多段,“数字字符串”会出现问题。而不是撕开字符串以找到字符串的部分上的WHERE子句的一个段的Max()+ 1。考虑这样的事情:
从用于递增和发布值的表开始:
{DocId Int, SegmentB int, SegmentC Int}
这将只跟踪要在其他表中使用的值。然后是一个存储过程来创建/增加一个新代码(MySQL - 这是一个概念性答案):
CREATE DEFINER=`root`@`localhost` PROCEDURE `GetNextProductCode`(in docId int,
in Minr int,
in Rev int
)
BEGIN
SET @maxR = 0;
SET @retCode ='';
if Minr =-1 then
Start transaction;
SET @maxR = (SELECT Max(SegmentB) FROM articlecode WHERE MainId = docId) + 1;
UPDATE articlecode SET SegmentB = @maxR WHERE MainId = docId;
Commit;
Select concat(Cast(docId As char) , '.',
Cast(@maxR AS char) , '.',
Cast(Rev As char)
);
end if;
END
这是一个大致的过程。因此,它只适用于第二段(我不知道当你创建一个新的SegmentB时会发生什么 - SegmentC重置为1 ???)。这个想法是:
有很多待办事项:
1000
和1
(?)默认值的新行要在之前获取新代码,请插入一行:
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("docId", MySqlDbType.Int32).Value = 3
cmd.Parameters.Add("Minr", MySqlDbType.Int32).Value = -1
cmd.Parameters.Add("Rev", MySqlDbType.Int32).Value = 1
dbcon.Open()
Using rdr = cmd.ExecuteReader()
rdr.Read()
Console.WriteLine(rdr(0))
End Using
明显的缺点是每个插入都需要你点击数据库以便...保存到数据库。如果它们是int值,则可以是Trigger。
答案 1 :(得分:0)
我是一名SQL开发人员,我的VB技能已经过时了大约十五年,但是不要在VB中自己创建增加的数字,而是让SQL使用IDENTITY字段生成它们。 SQL永远不会允许重复,然后你只需要返回SCOPE_IDENTITY():
ALTER TABLE dbo.tbArtikel
ADD [ArtikelID] INT IDENTITY(1,1) PRIMARY KEY;
答案 2 :(得分:0)