I have two tables: Table1 and Table2. I need newly inserted Id (from Table1
) as an output parameter which should be inserted into Table2
. And I must use SqlTransaction
or TransactionScope
here.
Stored procedure:
CREATE PROC InsertTable1
(
@Name nvarchar(50),
@OutputParam int out
)
AS
BEGIN
INSERT INTO Table1(Name)
VALUES(@Name)
SELECT @OutputParam = SCOPE_IDENTITY()
END
C# code:
SqlTransaction transaction = db.sqlconn.BeginTransaction();
SqlParameter[] param = new SqlParameter[2];
param[0] = new SqlParameter("@Name", "TestName");
param[1] = new SqlParameter("@OutputParam", SqlDbType.Int);
param[1].Direction = ParameterDirection.Output;
SqlHelper.ExecuteNonQuery(transaction, "InsertTable1", param);
int outputId = (int)param[1].Value;
When I run and debug the project I get an error
Object reference not set to an instance of an object
just after execution of
int outputId = (int)param[1].Value;
I think the transaction is closing the connection or something. It works if I don't use transaction. But I have to use transaction anyhow. I am open to any alternative ways to achieve the same result.
For problems concerning transactions take a look TransactionScope class. Here is the intro part from microsoft documentation .
The TransactionScope class provides a simple way to mark a block of code as participating in a transaction, without requiring you to interact with the transaction itself. A transaction scope can select and manage the ambient transaction automatically. Due to its ease of use and efficiency, it is recommended that you use the TransactionScope class when developing a transaction application.
Also you have transaction properties ( TransactionInformation and Current ) at your disposal to investigate status of transaction while debugging. This is all I can think of right now that wasn't suggested already.
First off, the overload of SqlHelper.ExecuteNonQuery
you are using takes an array of parameter values , not an array of SqlParameter
. It only compiles and runs because the type is object
. So it will derive its own parameters via a SqlCommandBuilder
and try to set the values on them from your param argument, but of course a SqlParameter cannot have a SqlParameter as its .Value
. The point is moot however, because the comments on the source code (below) specifically say you have no access to OUTPUT or RETURN values from this method.
/// <summary>
/// Execute a stored procedure via a SqlCommand (that returns no resultset) against the specified
/// SqlTransaction using the provided parameter values. This method will query the database to discover the parameters for the
/// stored procedure (the first time each stored procedure is called), and assign the values based on parameter order.
/// </summary>
/// <remarks>
/// This method provides no access to output parameters or the stored procedure's return value parameter.
///
/// e.g.:
/// int result = ExecuteNonQuery(conn, trans, "PublishOrders", 24, 36);
/// </remarks>
/// <param name="transaction">a valid SqlTransaction</param>
/// <param name="spName">the name of the stored procedure</param>
/// <param name="parameterValues">an array of objects to be assigned as the input values of the stored procedure</param>
/// <returns>an int representing the number of rows affected by the command</returns>
public static int ExecuteNonQuery(SqlTransaction transaction, string spName, params object[] parameterValues)
{
//if we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
//pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(transaction.Connection.ConnectionString, spName);
//assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
//call the overload that takes an array of SqlParameters
return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName, commandParameters);
}
//otherwise we can just call the SP without params
else
{
return ExecuteNonQuery(transaction, CommandType.StoredProcedure, spName);
}
}
USE OUTPUT
clause to get inserted data and save into a temporary table.
Return that data from stored procedure
您不需要在输出中获取值,如果您想在另一个表中插入数据,在存储过程中,您可以轻松编写另一个插入查询,将这个 id 插入另一个表中
我可以看到您正在使用自定义 SqlHelper.ExecuteNonQuery 方法来执行查询,能否请您分享 SqlHelper.ExecuteNonQuery 方法
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.