【问题标题】:Error in loading Data from SSIS errorlog table to a SQL Server table将数据从 SSIS 错误日志表加载到 SQL Server 表时出错
【发布时间】:2024-01-19 04:11:01
【问题描述】:

我在 SSIS 下创建了 Logging,它在我的数据库的系统表中生成为 [dbo].[sysssislog]。我正在尝试将特定列(如 Id、Source、starttime、endtime 和 message)获取到另一个 SQL Server 表、client.EximLog 和Client.EximLogHistory

每次我运行包时都会抛出以下错误:

在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, Boolean breakConnection, Action1 wrapCloseInAction) 在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔 breakConnection,Action1 wrapCloseInAction) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,布尔调用者HasConnectionLock,布尔异步关闭) 在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj,Boolean & dataReady) 在 System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(字符串方法名,布尔异步,Int32 超时,布尔异步写入) 在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 完成,字符串方法名,布尔 sendToPipe,Int32 超时,布尔和 usedCache,布尔异步写入,布尔 inRetry) 在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 在 ScriptMain.Input0_ProcessInputRow(Input0Buffer 行) 在 UserComponent.Input0_ProcessInput(Input0Buffer 缓冲区) 在 UserComponent.ProcessInput(Int32 InputID,字符串 InputName,PipelineBuffer 缓冲区,OutputNameMap OutputMap) 在 Microsoft.SqlServer.Dts.Pipeline.ScriptComponent.ProcessInput(Int32 InputID,PipelineBuffer 缓冲区) 在 Microsoft.SqlServer.Dts.Pipeline.ScriptComponentHost.ProcessInput(Int32 inputID, PipelineBuffer 缓冲区)

我创建了一个事件处理程序“Onerror”来执行数据流任务,例如“连接到 SSIS 日志表”。

在数据流任务中,我使用 OLD DB Connection 连接到 sysssislog 表。

SELECT Id, source, starttime, endtime, message 
FROM dbo.sysssislog
WHERE event = 'onerror' AND ID NOT IN (SELECT ISNULL(cast(LogId as int), 0)  FROM [Client].[EximLog])

我已将 OLD DB 源连接作为目标连接到脚本组件。我正在执行以下存储过程。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[spEximLog]
--Add parameters for the stored procedure
    @pSystemID nvarchar(max) = NULL,
    --@sEvent nvarchar(max) = NULL,
    @pSource nvarchar(max) = NULL,
    @pStarttime nvarchar(max) = NULL,
    @pEndtime nvarchar(max) = NULL,
    @pMessage nvarchar(max) = NULL
    WITH EXECUTE AS OWNER
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @vJoboutcome nvarchar(max);
    DECLARE @vGUID nvarchar(40);
    DECLARE @vTimeStamp timestamp;
    DECLARE @vEximID int;
    DECLARE @vDefaultOperation nvarchar(40);
    DECLARE @vDefaultEventRegistrationId int;
    DECLARE @vDefaultVersion int;

    SET @vJoboutcome = 'F';
    SET @vDefaultOperation = 'Insert';
    SET @vDefaultEventRegistrationId = 1;
    SET @vDefaultVersion = 1;


    IF NOT EXISTS (SELECT * FROM [dbo].[sysssislog] WHERE ID = @pSystemID)

    BEGIN

        SET @vGUID = CAST((SELECT NEWID()) as nvarchar(40));

        --Inserting 8 cloumns into Exim table
        INSERT INTO [Client].[EXIMLog]
        (
          [JobName], [JobMessage], [JobOutCome], [LogID], [DtmJobStart], [DtmJobEnd]
        , [EventRegistrationId], [ObjectId]
        )

        VALUES(@pSource, @pMessage, @vJoboutcome, @pSystemID, @pStarttime, @pEndtime
        , @vDefaultEventRegistrationId, @vGUID);

        SET @vEximID = (SELECT @@IDENTITY); /*Same EximId is used in Malvern import and in its history table*/

        --Stores the timestamp for the row using where clause
        SET @vTimeStamp = (SELECT [TimeStamp] from [Client].[EXIMLog] where Id = @vEximId);


        --Inserting 12 cloumns into Exim History table
        INSERT INTO [Client].[EXIMLogHistory]
        (
          [Id], [Version], [JobName], [JobMessage], [JobOutCome], [LogID], [DtmJobStart]
        , [DtmJobEnd], [EventRegistrationId], [ObjectId], [Operation], [TimeStamp]
        )
        VALUES(@vEximID, @vDefaultVersion, @pSource, @pMessage, @vJoboutcome, @pSystemID,  @pStarttime, @pEndtime, @vDefaultEventRegistrationId, @vGUID
        , @vDefaultOperation, CAST(@vTimeStamp as varbinary));
    END
END;
GO

以下是我在脚本组件中使用的脚本,连接管理器是 ADO.net 连接。

#region Namespaces
using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
#endregion

public override void Input0_ProcessInputRow(Input0Buffer Row)
{
    System.Data.SqlClient.SqlConnection conn =
        (System.Data.SqlClient.SqlConnection)Connections.SecondConnection.AcquireConnection(null);
    System.Data.SqlClient.SqlCommand cmd = new
        System.Data.SqlClient.SqlCommand("Exec [dbo].[spEximLog]'" + Row.Id + "', '" + Row.source + "', '" + Row.starttime +"', '" + Row.endtime + "' , '" + Row.message + "'", conn);
    cmd.ExecuteNonQuery();
}

【问题讨论】:

  • 您发布的“错误”不是错误消息。这是堆栈跟踪。再看一遍,看看你能不能找到真正的错误。
  • 我发现 'message' 列的单引号中有一个单词 'spEximlog'。所以改变了传递脚本的方式如下,它起作用了。

标签: c# sql-server logging error-handling ssis


【解决方案1】:

修改脚本组件代码如下,问题解决。

public override void PostExecute()
    {
        base.PostExecute();

        conn.Close();

    }

public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        if(conn.State != System.Data.ConnectionState.Open)
        {
            conn.Open();
        }
        System.Data.SqlClient.SqlCommand cmd = new
            System.Data.SqlClient.SqlCommand("[dbo].[spEximLog]", conn);
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@pSystemID", Row.Id));
        cmd.Parameters.Add(new SqlParameter("@pSource", Row.source));
        cmd.Parameters.Add(new SqlParameter("@pstarttime", Row.starttime));
        cmd.Parameters.Add(new SqlParameter("@pendtime", Row.endtime));
        cmd.Parameters.Add(new SqlParameter("@pmessage", Row.message));

        cmd.ExecuteNonQuery();
    }

独立分配参数。在 post 执行中关闭连接,使其不会达到最大连接池。

【讨论】: