This is my code part:
CResponseVO objCResponseVO = new CResponseVO();
try
{
var parameters = new DynamicParameters();
parameters.Add("@UserId", currentUser.userId, DbType.Int32);
parameters.Add("@Operation", operation, DbType.String);
parameters.Add("@Output", dbType: DbType.Int32, direction: ParameterDirection.Output);
using (var connection = SqlAccessHelper.SqlHelper.GetOpenConnection(SqlConnectionHelper.SqlConnectionString()))
{
var reader = connection.QueryMultiple("USP_DataExtract", parameters, (SqlTransaction)null, 1000000, CommandType.StoredProcedure);
int result = parameters.Get<int>("@Output");
if (operation != "insert")
{
ObservableCollection<DataExtraction.DataExtractionTracker> DataExtractionTracker = new ObservableCollection<DataExtraction.DataExtractionTracker>(reader.Read<DataExtraction.DataExtractionTracker>());
objCResponseVO.addObject("ExtractionStatus", DataExtractionTracker);
}
objResponseVO.Result = result;
}
This is my SP, and I have used try and catch to commit or rollback based on ouput parameter value:
@UserID int=0,
@Operation varchar(50)= NULL,
@Output INT OUTPUT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
If(@Operation = 'select')
BEGIN
SELECT RequestId, UserId, RequestTime, Status,DownloadPath from DataExtractTracker where UserId= @UserID
END
If(@Operation = 'insert')
BEGIN
Insert into DataExtractTracker( UserId, RequestTime, Status) values (@UserID, GETDATE(), 'Waiting')
END
SET @Output = 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SET @Output = 1
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE();
-- Use RAISERROR inside the CATCH block to return
-- error information about the original error that
-- caused execution to jump to the CATCH block.
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.);
END CATCH
END
However, I am not able to retrieve the ouput parameter value. I am getting an exception when executing:
int result = parameters.Get<int>("@Output");
Exception says something like this:
Object reference not set to an instance of an object.
This is simply a feature of TDS, and you would get the same with ADO.NET; the returned parameter values are usually at the end of the TDS stream; consequently, the updated values are not available until after you have finished consuming the data.
Basically, you need to query the parameter values after you have finished with reader, because until then the value has not come back. For example, the following hastily added integration test passes:
public void TestOutputParameter()
{
connection.Execute(@"
create proc #TestOutputParameterProc @Foo int, @Bar int out as
set @Bar = @Foo select 1 as [A] select 2 as [B]");
try
{
var args = new DynamicParameters(new { Foo = 123 });
args.Add("@Bar", dbType: DbType.Int32,
direction: ParameterDirection.Output);
using (var grids = connection.QueryMultiple("#TestOutputParameterProc",
args, commandType: CommandType.StoredProcedure))
{
// this will fail here; we have not consumed the TDS data yet!
// args.Get<int>("@Bar").IsEqualTo(123);
// note we don't *have* to read the data here; disposing "grids"
// would be enough to skip to the end of the TDS
grids.Read<int>().Single().IsEqualTo(1); // A
grids.Read<int>().Single().IsEqualTo(2); // B
}
// at this point we have consumed the TDS data, so the parameter
// values have come back to the caller
args.Get<int>("@Bar").IsEqualTo(123);
}
finally
{ // clean up the proc
connection.Execute("drop proc #TestOutputParameterProc");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With