我有一个调用web服务的ASP .net应用程序。 Web服务调用数据访问类来更新数据库。
我的网络服务中有一段代码片段(实际上是伪代码),类似于以下内容:
Public Function SubmitCheque(//params are passed here)
//Call sql stored procedure(SP1) to generate a reference Number
//Begin loop. loop count would be number of records that are in a collection
//Insert records to database using another stored procedure(SP2) using the
//reference number generated in the previous step
//End Loop
End Function
SP1对表执行选择查询,获取最后一行的列值,然后将其序列递增1.假设最后一行的值是ABC02282012 * 56 *,那么我的新参考号将是ABC02282012 * 57 *
SP2执行单个insert语句,它插入的行将具有生成的引用号。
这是预计会出现的问题,我不确定正确的方法。
在我的代码中,SP1和SP2按顺序执行,并且在SP1和SP2之间的毫秒时间间隔内,应用程序的另一个实例可能已执行SP1并且可以获得相同的事务编号。因此,有可能同时访问应用程序的多个用户可能最终获得相同的交易号,这是一个大问题。
我想知道这是SQL服务器会关注的事情,还是我需要以不同的方式重新编写存储过程或代码来实现事务。
请帮助并告诉我您的意见。
答案 0 :(得分:2)
您可以更好地在单个存储过程中实现所有逻辑,并将语句包装在合适的事务中。
未能使用TransactionScope在交易中登记您的单独操作。 e.g:
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Call sql stored procedure(SP1) to generate a reference Number
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteScalar();
//Begin loop. loop count would be number of records that are in a collection
//Insert records to database using another stored procedure(SP2) using the
//reference number generated in the previous step
//End Loop
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}