I have an issue which is causing my SSIS package failure in its first execution, while on 2nd onward execution the issue is automatically resolved and the SSIS package is executed successfully.
Project: Migrating a package
- SQL Server 2008 R2 to SQL Server, SSDT 2016
- Visual Studio 2008 to Visual Studio 2015
Case:
One of my migrated SSIS packages which has a script task to:
- Execute stored procedure with one OUTPUT parameter to get rows count
- Write the returned rows to a txt file in CSV format.
The stored procedure get executed under this script tasks; returns (thousands, millions of rows) along with one OUTPUT parameter which contains rows count return by the stored procedure.
Problem:
This SSIS Package is failing randomly on 1st execution with error -
"Object cannot be cast from DBNULL to other types"
and on its 2nd execution is executed successfully.
When we Google this error, the most common solution found is to check the Variable value first: whether it's an INT value, and has any value, and then only converts.
However, this solution does not apply here, as when I execute the SSIS package a 2nd time, it gets executed successfully.
One more thing to note here is that when the SSIS Package randomly fails, it writes the CSV file with an incomplete row, and on 2nd execution this issue is also resolved.
It looks like the above error is not actual error and due to unknown reasons not giving actual error.
Is it due to any configuration missing on SSIS / SQL level or any other issue?
Please find the SCRIPT & stored procedure code below.
Every random failure caught at below line of SCRIPT code. However, on 2nd run no such issue appeared. So, looks like its not a conversion issue but more towards 2016 configuration or some different way of coding issue -
listRowCounts.Add(Convert.ToInt32(outputparm.Value));
Please find below the:
script task code part under which the error is coming &
Stored procedure code part by which we are deriving the rows count and setting it in OUTPUT variable
In Script task below code, there are multiple logging points created to know till what point the code is running as-
// Write to sysout
Console.WriteLine("Test<NUMBER>");
--||--**-- --||--**-- --||--**-- --||--**-- --||--**--
SCRIPT code part for WriteData only--
public void WriteData(string strExamRegionCode, string strdivisionCode, string strResultFileName, DateTime dtmStdDate)
{
SqlConnection conn = new SqlConnection(strConnectionStringLog);
SqlCommand cmd = null;
SqlDataReader rdr = null;
try
{
//Open the connection
conn.Open();
// Create the command
cmd = new SqlCommand("usp_Exam_ResultManifest_ProcList_Get", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@Exam_region_code", strExamRegionCode));
cmd.Parameters.Add(new SqlParameter("@Exam_division_code", strdivisionCode));
cmd.Parameters.Add(new SqlParameter("@Result_file_name", strResultFileName));
// Return the resultset
rdr = cmd.ExecuteReader();
// Write to sysout
Console.WriteLine("Test12");
// Fail if no rows returned
if (!rdr.HasRows)
{
// Log error to database
string strCustomMessage = "No data returned by calling stored procedure usp_Exam_ResultManifest_ProcList_Get with parameters: " + strExamRegionCode + ", " + strdivisionCode + ", " + strResultFileName + ", " + dtmStdDate.ToString("yyyyMMdd");
LogCustomMessage(strConnectionStringLog, "OnError", strMachineName, strUserName, strPackageName, strPackageID, strExecutiondivisionGUID, strContainerStartTime, 100, strCustomMessage);
// Write to sysout
Console.WriteLine(strCustomMessage);
// Fail the package - error will be written to table sysssislog
throw new MyAppException(strCustomMessage);
}
else
{
// Call the Result Get stored procedure(s) to retrieve the Result data
while (rdr.Read())
{
// Get the stored procedure name
string strResultGetStoredProcedureName = rdr["Result_get_storedprocedure_name"].ToString();
// Write to sysout
Console.WriteLine("Test13");
try
{
SqlConnection connFDA = new SqlConnection(strConnectionStringResult);
SqlCommand cmdFDA = null;
SqlDataReader rdrFDA = null;
//Open the connection
connFDA.Open();
// Run the sproc to return the Result data
cmdFDA = new SqlCommand(strResultGetStoredProcedureName, connFDA);
cmdFDA.CommandType = CommandType.Text;
SqlParameter parm1 = new SqlParameter("@Std_date", SqlDbType.DateTime);
parm1.Value = dtmStdDate;
parm1.Direction = ParameterDirection.Input;
cmdFDA.Parameters.Add(parm1);
SqlParameter parm2 = new SqlParameter("@Exam_Source_Section_division", SqlDbType.VarChar);
parm2.Value = strdivisionCode;
parm2.Direction = ParameterDirection.Input;
cmdFDA.Parameters.Add(parm2);
SqlParameter outputparm = new SqlParameter("@rows_returned", SqlDbType.Int);
outputparm.Direction = ParameterDirection.Output;
outputparm.Size = int.MaxValue;
cmdFDA.Parameters.Add(outputparm);
// Write to sysout
Console.WriteLine("Test14");
if (Dts.Variables["strForceRecompileObjects"].Value.ToString().Contains(strResultGetStoredProcedureName))
{
cmdFDA.CommandText = cmdFDA.CommandText + " @Std_date, @Exam_Source_Section_division, @rows_returned OUT WITH RECOMPILE;";
// Write to sysout
Console.WriteLine("Test15");
}
else
{
cmdFDA.CommandText = cmdFDA.CommandText + " @Std_date, @Exam_Source_Section_division, @rows_returned OUT;";
// Write to sysout
Console.WriteLine("Test16");
}
// Result file generation timeout issue
cmdFDA.CommandTimeout = 1600;
// Write to sysout
Console.WriteLine("B4_cmdFDA_Execution");
// Return the resultset
rdrFDA = cmdFDA.ExecuteReader();
// Write to sysout
Console.WriteLine("AFTER_cmdFDA_Execution");
if (rdrFDA.HasRows)
{
// Write to sysout
Console.WriteLine("rdrFDA has rows.");
}
else
{
// Write to sysout
Console.WriteLine("rdrFDA has NO rows.");
}
// Write to sysout
Console.WriteLine("TT");
// Write to sysout
Console.WriteLine("Test17");
try
{
// Loop through the Result data and write to the file
while (rdrFDA.Read())
{
// Write the row data to the file
string strRowData = rdrFDA["row_data"].ToString();
// Write to sysout
//Console.WriteLine("Test18");
int intControlId = Convert.ToInt32(rdrFDA["Result_control_id"]);
if (!listControlIds.Contains(intControlId))
{
listControlIds.Add(intControlId);
// Write to sysout
Console.WriteLine("Test19");
}
WriteFile(strRowData);
// Write to sysout
//Console.WriteLine("Test20");
}
}
catch (Exception ex)
{
// Log error to database
string strCustomMessage = "Error rdrFDA.Read - stored procedure " + strResultGetStoredProcedureName + " with parameters: " + dtmStdDate.ToString("yyyyMMdd") + ", " + strdivisionCode + ", Error: " + ex.Message;
LogCustomMessage(strConnectionStringLog, "OnError", strMachineName, strUserName, strPackageName, strPackageID, strExecutiondivisionGUID, strContainerStartTime, 100, strCustomMessage);
// Write to sysout
Console.WriteLine(strCustomMessage);
// Fail the package - error will be written to table sysssislog
throw;
}
// Close the reader
rdrFDA.Close();
// Write to sysout
Console.WriteLine("Test21");
// Write to sysout
Console.WriteLine("abc");
Console.WriteLine("xyz" + Convert.ToString(outputparm.Value));
Console.WriteLine("def");
// Keep track of row counts - for the trailer row (MUST be after closing the reader)
listRowCounts.Add(Convert.ToInt32(outputparm.Value));
// Write to sysout
Console.WriteLine("Test22");
// Close the connection
connFDA.Close();
}
catch (Exception ex)
{
// Log error to database
string strCustomMessage = "Error retrieving data for writing to the output file - stored procedure " + strResultGetStoredProcedureName + " with parameters: " + dtmStdDate.ToString("yyyyMMdd") + ", " + strdivisionCode + ", Error: " + ex.Message;
LogCustomMessage(strConnectionStringLog, "OnError", strMachineName, strUserName, strPackageName, strPackageID, strExecutiondivisionGUID, strContainerStartTime, 100, strCustomMessage);
// Write to sysout
Console.WriteLine(strCustomMessage);
// Fail the package - error will be written to table sysssislog
throw;
}
}
rdr.Close();
conn.Close();
}
}
catch (Exception ex)
{
// Log error to database
string strCustomMessage = "Error retrieving data for writing to the output file with parameters: " + strExamRegionCode + ", " + strdivisionCode + ", " + strResultFileName + ", " + dtmStdDate.ToString("yyyyMMdd") + ", Error: " + ex.Message;
LogCustomMessage(strConnectionStringLog, "OnError", strMachineName, strUserName, strPackageName, strPackageID, strExecutiondivisionGUID, strContainerStartTime, 100, strCustomMessage);
// Write to sysout
Console.WriteLine(strCustomMessage);
// Fail the package - error will be written to table sysssislog
throw;
}
}
--||--**-- --||--**-- --||--**-- --||--**-- --||--**--
--||--**-- --||--**-- --||--**-- --||--**-- --||--**--
---Stored proedure code where setting OUTPUT parameter value ONLY: -
CREATE PROCEDURE [dbo].[p_result_get_SchoolItems_exam_v18]
@std_date DATETIME = NULL,
@exam_Source_Section_division VARCHAR(10) = NULL,
@rows_returned INT OUTPUT,
@debug TINYINT = 0
WITH EXECUTE AS CALLER
AS
SET NOCOUNT ON
/*
** Declare and set error tracking and debugging variables
*/
DECLARE @ProcName sysname,
@Error int,
@Raiserror int,
@CustomErrorSeverity int ,
@CustomErrorState int,
@ErrorSeverity int ,
@ErrorState int,
@Msg varchar(255),
@Rowcount int,
@RowCnt int;
SET @ProcName = object_name(@@procid);
SET @Error = 0;
SET @Raiserror = 0;
SET @Msg = '';
SET @Rowcount = 0;
SET @RowCnt = 0;
SET @CustomErrorSeverity = 11;
SET @CustomErrorState = 1;
/*
** Declare variables used to implement procedure specific functionality
*/
DECLARE @default_date datetime;
DECLARE @working_date datetime;
DECLARE @exam_region_code varchar(10);
DECLARE @SchoolID varchar(8);
DECLARE @result_control_id int;
SELECT @default_date = '29991231';
BEGIN TRY
IF (@debug>=1) PRINT @ProcName + ' : ' + convert(varchar(30),getdate(),109) + ': Entering procedure ...';
--To avoid NULL/DBNULL issues coming in SSIS Package execution due to below direct SET via @@ROWCOUNT; added same Query as above but with COUNT(1) only.
--SET @rows_returned = @@ROWCOUNT;
SELECT @RowCnt = COUNT(1)
FROM dbo.t_result_SchoolItems_exam result
JOIN dbo.t_result_VerificationList_exam con
ON result.result_control_id = con.result_control_id
AND con.exam_division_code = result.exam_division_code
JOIN dbo.t_result_name_exam n
ON con.result_name_id = n.result_name_id
JOIN dbo.t_result_Active_Verification_id_exam curr
ON con.result_control_id = curr.result_control_id
AND curr.exam_division_code = result.exam_division_code
WHERE n.result_name = 'PatternD book'
AND con.exam_region_code = @exam_region_code
AND con.exam_bus_date = @std_date
AND result.exam_division_code = @exam_Source_Section_division
--ORDER BY result.system_id, result.Roll_ID, result.Ce_value_local_ledgerK, result.due_local_ledgerK, result.cash_amount_local_ledgerK
OPTION (RECOMPILE);
SET @rows_returned = @RowCnt;
END TRY
BEGIN CATCH
SELECT @Raiserror = 300000 + error_number() ,
@ErrorSeverity = error_severity() ,
@ErrorState = error_state() ,
@Msg = @ProcName + ': ' + isnull ( error_message() , @Msg ) + ' , Error Number = ' + isnull ( convert ( varchar , error_number()) , '' )
+ ' , Error Line = ' + isnull ( convert ( varchar , error_line()) , 'N/A' );
RAISERROR (@Msg, @ErrorSeverity, @ErrorState);
RETURN @Raiserror;
END CATCH;
GO
--||--**-- --||--**-- --||--**-- --||--**-- --||--**--