У меня есть проблема, которая вызывает сбой моего пакета служб SSIS при его первом выполнении, в то время как при втором последующем выполнении проблема автоматически решается, и пакет служб SSIS выполняется успешно.
Проект: миграция пакета
- SQL Server 2008 R2 для SQL Server, SSDT 2016
- Visual Studio 2008 для Visual Studio 2015
Дело:
Один из моихперенесены пакеты служб SSIS, в которых есть задача сценария:
- Выполнить хранимую процедуру с одним параметром OUTPUT, чтобы получить количество строк
- Записать возвращенные строки в текстовый файл в формате CSV.
Хранимая процедура выполняется по заданию этого скрипта;возвращает (тысячи, миллионы строк) вместе с одним параметром OUTPUT, который содержит число строк, возвращаемое хранимой процедурой.
Проблема:
Этот пакет служб SSIS случайно завершается при первом выполнении с ошибкой -
"Объект не может быть приведен из DBNULL к другим типам"
и при его втором выполнении выполняется успешно.
Когда мы погуглили эту ошибку,Наиболее распространенное найденное решение - сначала проверить значение переменной: является ли оно значением INT и имеет ли какое-либо значение, а затем только преобразует.
Однако это решение здесь не применяется, как при выполнении пакета служб SSIS.во второй раз он успешно выполняется.
Еще одна вещь, на которую следует обратить внимание, это то, что при случайном сбое пакета SSIS он записывает CSV-файл с неполной строкой, и при втором выполнении эта проблема также решается.
Похоже, что вышеуказанная ошибка не является действительной ошибкой и по неизвестным причинам не дает действительной ошибки.
Является ли это dЕсли какая-либо конфигурация отсутствует на уровне служб SSIS / SQL или есть какие-либо другие проблемы?
Ниже приведен код SCRIPT и хранимой процедуры.
Каждый случайный сбой обнаруживается в нижней строке кода SCRIPT. Однако при втором запуске такой проблемы не возникло.Так что, похоже, это не проблема конверсии, а скорее проблема конфигурации 2016 года или какой-то другой способ кодирования -
listRowCounts.Add(Convert.ToInt32(outputparm.Value));
Ниже вы найдете:
часть кода задачи скрипта, в которой появляется ошибка &
Часть кода хранимой процедуры, по которой мы получаем число строк и устанавливаем его в переменной OUTPUT
В задаче «Сценарий» под кодом существует несколько точек входа, созданных, чтобы знать, до какой точки выполняется код :-
// 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
--||--**-- --||--**-- --||--**-- --||--**-- --||--**--