用FK将事务插入到第一行创建的行中
问题描述:
我有一批需要在单个事务中插入的行,第一行是标题,所有后续行必须引用第一行。用FK将事务插入到第一行创建的行中
这是我正在试图插入的第一行:
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
var transaction = connection.BeginTransaction();
try
{
// create the record header
using (var createRecordCommand = connection.CreateCommand())
{
createRecordCommand.CommandText =
"DECLARE @RecordId INT;" +
$"INSERT INTO ..." +
"SET @RecordId = scope_identity();";
createRecordCommand.Transaction = transaction;
createRecordCommand.ExecuteNonQuery();
我挣扎引用的recordId在随后的声明,似乎觉得变量@RecordId没有在下面的代码片段声明。 '必须声明标量变量“@RecordId”。'
using (var createAttributeCommand = connection.CreateCommand())
{
createAttributeCommand.Transaction = transaction;
createAttributeCommand.CommandText =
$"INSERT INTO ... (RecordId,...) VALUES (@RecordId,...)";
而且提取作为一个参数被证明是困难@RecordId变量,它不喜欢它,当我用下面的线结合DECLARE @RecordId INT;
createRecordCommand.Parameters.Add(new SqlParameter("@RecordId", SqlDbType.Int) { Direction = ParameterDirection.Output });
答
我没有意识到你可以在事务提交之前提取数据,假设由于ExecuteScalar()不起作用,我会遇到同样的问题。
正如评论中指出的那样,存储过程可能是最好的解决方案,SQL专家在一段时间后听起来像破碎的记录; p。由于存在可变参数数量,因此短期而言这将过于复杂,验证和值将根据业务逻辑进行变异。作为一个团队,我们在C#中更加舒适,因此逻辑将一直保持到完全确定下来。
结果代码如下,N.B.在实际的代码,通过所有变量作为参数,以避免SQL注入,我们到了,这是演示仅:
using (var connection = new SqlConnection(_connectionString))
{
connection.Open();
var transaction = connection.BeginTransaction();
try
{
// create the record header
using (var createRecordCommand = connection.CreateCommand())
{
createRecordCommand.CommandText =
//"DECLARE @RecordId INT;" +
$"INSERT INTO ..." +
"SET @RecordId = scope_identity();";
createRecordCommand.Transaction = transaction;
createRecordCommand.Parameters.Add(new SqlParameter("@RecordId", SqlDbType.Int) { Direction = ParameterDirection.Output });
createRecordCommand.ExecuteNonQuery();
recordId = (int) createRecordCommand.Parameters["@RecordId"].Value;
// ...
using (var createAttributeCommand = connection.CreateCommand())
{
createAttributeCommand.Transaction = transaction;
createAttributeCommand.CommandText =
$"INSERT INTO ... (RecordId,...) VALUES ({recordId},...)";
// ...
transaction.Commit();
你为什么不把你的逻辑放到一个存储过程,然后就调用从C#程序? –
我已经削减了问题的复杂性,我们试图实现的过程对于存储过程而言非常复杂,不幸的是。 –
嗯,是什么?存储过程过于复杂?将插入作为存储过程执行,并使用OUTPUT参数返回标识。 –