【发布时间】:2012-08-26 19:54:49
【问题描述】:
在执行 SQL Server 事务时如何防止出现以下错误?
我正在尝试将SupplierOrder 和VehicleRecord 添加到一组两个数据库表中。我正在使用以下内容:
表 SQL 结构:
CREATE TABLE VSI_VehicleRecords
(
VehicleRecordID INT IDENTITY(1,1) PRIMARY KEY,
StockNumber INT NOT NULL,
Status INT NOT NULL,
Make VARCHAR(50) NOT NULL,
Model VARCHAR(50) NOT NULL,
Colour VARCHAR(50) NOT NULL,
Spefication VARCHAR(255) NOT NULL
)
CREATE TABLE VSI_SupplierOrders
(
SupplierOrderID INT IDENTITY(1,1) PRIMARY KEY,
VehicleRecordID INT FOREIGN KEY REFERENCES VSI_VehicleRecords(VehicleRecordID) UNIQUE,
Timestamp
)
我编写了一个实用方法,它将一组 Sql 查询作为事务运行:
C#执行事务:
SqlTransaction _Transaction;
OpenConnection();
_Transaction = __Connection.BeginTransaction();
try
{
for (int i = 0; i < Commands.Length; i++)
{
Commands[i].Connection = __Connection;
Commands[i].Transaction = _Transaction;
Commands[i].ExecuteNonQuery();
}
_Transaction.Commit();
return true;
}
catch (SqlException e)
{
_Transaction.Rollback();
}
上述函数要执行的SQL命令:
SqlCommand[] _Commands = new SqlCommand[2];
string _InsertVehicleQuery = "INSERT INTO VSI_VehicleRecords(StockNumber,Status,Make,Model,Colour,Spefication) VALUES (@StockNumber, @Status, @Make, @Model, @Colour, @Specification);";
SqlCommand _InsertVehicleCommand = new SqlCommand(_InsertVehicleQuery);
_InsertVehicleCommand.Parameters.AddWithValue("@StockNumber", __StockNumber);
_InsertVehicleCommand.Parameters.AddWithValue("@Status", __Status);
_InsertVehicleCommand.Parameters.AddWithValue("@Make", Make);
_InsertVehicleCommand.Parameters.AddWithValue("@Model", Model);
_InsertVehicleCommand.Parameters.AddWithValue("@Colour", Colour);
_InsertVehicleCommand.Parameters.AddWithValue("@Specification", Specification);
_Commands[0] = _InsertVehicleCommand;
string _InsertSupplierOrderQuery = "INSERT INTO VSI_SupplierOrders(VehicleRecordID) VALUES (@VehicleRecordID);";
SqlCommand _InsertSupplierOrderCommand = new SqlCommand(_InsertSupplierOrderQuery);
_InsertSupplierOrderCommand.Parameters.AddWithValue("@VehicleRecordID", _VehicleRecordID);
_Commands[1] = _InsertSupplierOrderCommand;
DataUtility.NonQueryTransaction(_Commands);
但是我收到以下错误:
*INSERT 语句与 FOREIGN KEY 约束“FK__VSI_Suppl_Vehic_5165187F”冲突。数据库发生冲突 “jack_test”,表“dbo.VSI_VehicleRecords”,列“VehicleRecordID”。*
【问题讨论】:
-
您如何确定您在第二个命令中插入的
_VehicleRecordID值?如果是上一个命令中的IDENTITY- 你如何获取/检索它??? -
@marc_s 在运行查询之前,我使用“Select * MAX(...) ..”查询来确定下一个主键。
-
Jack - 在使用
IDENTITY列时,没有可靠的方法来确定下一个主键。由于系统中的并发活动,或由于可能已失败并回滚的事务,IDENTITY列的 next 值不始终为MAX() + 1......不要使用那种技术 - 它非常不可靠。相反:让 SQL Server 使用IDENTITY列完成它的工作,并获取 SQL Server 已分发的值。只有在INSERT实际发生之后,IDENTITY列的“下一个”值才真正确定并且可以读取。 -
查看 podiluska 的回答 - 这是使用
IDENTITY列的唯一可靠方法:(1) 将行插入表中,(2) 获取实际值使用SCOPE_IDENTITY()插入 - 没有其他方法可以可靠地工作 -
为什么要使用多个命令?使用一个命令。循环加载带有参数的命令并执行命令。而 Select Scope_Identity 是如何检索 Iden 的。
标签: c# sql sql-server-2008 tsql