从 SSIS 中的 ADO 连接获取连接字符串的问题

Issue in getting connectionstring from ADO Connection in SSIS

我花了几个小时才找出真正的问题。问题来了。

我在 SSIS 2005 包中有一个 VB.Net 脚本任务。脚本任务的目的是从一个数据库批量插入到另一个数据库(在不同的服务器中)。我正在使用 .Net 中的 SQlBulkCopy class 进行插入。当我使用 windows 身份验证时它工作正常。

现在我将其设为 SQL Server Authentication 并使用 expressions 从配置文件中存储的变量值创建连接字符串。 SSIS 能够成功获取 ADO 连接——但是当我从 connection object 中提取连接字符串时,它没有提供密码——它吞下了密码。

Dim destinationConnection As New SqlConnection()
destinationConnection = DirectCast(TryCast(Dts.Connections("ADOACIConnection").AcquireConnection(Dts.Transaction), SqlConnection), SqlConnection)

Dim destinationConnectionString As String = destinationConnection.ConnectionString
MessageBox.Show(destinationConnectionString)  'It is not getting password when using SQL Server Authentication
PerformBulkCopy(tableName, sourceConnection, destinationConnectionString)

问题

  1. 如何获取带密码的连接字符串?

代码

Public Sub PerformBulkCopy(ByVal tableName As String, ByVal sourceConnection As SqlConnection, ByVal destinationConnectionString As String)
    Dim dtSource As DataTable
    dtSource = New System.Data.DataTable()
    dtSource = GetSourceDataTable(tableName, sourceConnection)


    Using sbc As New SqlBulkCopy(destinationConnectionString)
        sbc.DestinationTableName = tableName
        sbc.WriteToServer(dtSource)
    End Using
End Sub


Public Function GetSourceDataTable(ByVal tableName As String, ByVal sourceConnection As SqlConnection) As DataTable

    Dim cmd As New SqlCommand("uspGetDataForAchival")
    cmd.Parameters.Add(New SqlParameter("@TableName", tableName))
    cmd.CommandType = CommandType.StoredProcedure
    cmd.Connection = sourceConnection

    Dim dap As New SqlDataAdapter(cmd)
    Dim ds As New DataSet()
    dap.Fill(ds)
    Return ds.Tables(0)

End Function

Public Sub Main()

    Dim tableName As String = Dts.Variables("User::CurrentTable").Value.ToString()
    Dim sourceConnection As New SqlConnection()

    Try

        sourceConnection = DirectCast(TryCast(Dts.Connections("ADOSourceConnection").AcquireConnection(Dts.Transaction), SqlConnection), SqlConnection)

        Dim destinationConnection As New SqlConnection()
        destinationConnection = DirectCast(TryCast(Dts.Connections("ADOACIConnection").AcquireConnection(Dts.Transaction), SqlConnection), SqlConnection)

        Dim destinationConnectionString As String = destinationConnection.ConnectionString
        MessageBox.Show(destinationConnectionString)  
        PerformBulkCopy(tableName, sourceConnection, destinationConnectionString)

        Dts.TaskResult = Dts.Results.Success

    Catch ex As Exception

        Dim exceptionVariable As Microsoft.SqlServer.Dts.Runtime.Variables = Nothing
        Dts.VariableDispenser.LockOneForWrite("User::ScriptException", exceptionVariable)
        exceptionVariable("User::ScriptException").Value = ex.Message
        exceptionVariable.Unlock()
        Dts.Events.FireError(-1, "Task Name", ex.Message, String.Empty, 0)
        Dts.TaskResult = Dts.Results.Failure
    End Try

End Sub

感谢@billinkc 添加对 Todd McDermid 博客 Post 关于 Use Connections Properly in an SSIS Script Task

的引用

我读的另一篇文章是MSDN - SSIS Team Blog - Accessing OLEDB Connection Managers in a Script

最后我修改了代码以解决问题并按照上述博客 post 建立连接。我没有从连接字符串创建连接,而是传递了连接对象来执行 SqlBulkCopy。效果很好。

    Public Sub PerformBulkCopy(ByVal tableName As String, ByVal sourceConnection As SqlConnection, ByVal destinationConnection As SqlConnection)
    Dim dtSource As DataTable
    dtSource = New System.Data.DataTable()
    dtSource = GetSourceDataTable(tableName, sourceConnection)


    Using sbc As New SqlBulkCopy(destinationConnection)
        sbc.DestinationTableName = tableName
        sbc.WriteToServer(dtSource)
    End Using
End Sub


Public Function GetSourceDataTable(ByVal tableName As String, ByVal sourceConnection As SqlConnection) As DataTable

    Dim cmd As New SqlCommand("uspGetDataForAchival")
    cmd.Parameters.Add(New SqlParameter("@TableName", tableName))
    cmd.CommandType = CommandType.StoredProcedure
    cmd.Connection = sourceConnection

    Dim dap As New SqlDataAdapter(cmd)
    Dim ds As New DataSet()
    dap.Fill(ds)
    Return ds.Tables(0)

End Function

Public Sub Main()

    Dim tableName As String = Dts.Variables("User::CurrentTable").Value.ToString()
    Dim sourceConnection As SqlConnection
    Dim destinationConnection As SqlConnection

    Try
        ' Retrieve the reference to the managed connection'
        Dim cmSource As ConnectionManager
        cmSource = Dts.Connections("ADOSourceConnection")
        sourceConnection = DirectCast(cmSource.AcquireConnection(Dts.Transaction), System.Data.SqlClient.SqlConnection)

        Dim cmDestination As ConnectionManager
        cmDestination = Dts.Connections("ADOACIConnection")
        destinationConnection = DirectCast(cmDestination.AcquireConnection(Dts.Transaction), System.Data.SqlClient.SqlConnection)

        Dim destinationConnectionString As String = destinationConnection.ConnectionString
        MessageBox.Show(destinationConnectionString)
        PerformBulkCopy(tableName, sourceConnection, destinationConnection)

        'Release Connection'
        cmSource.ReleaseConnection(sourceConnection)
        cmDestination.ReleaseConnection(destinationConnection)

        'Success'
        Dts.TaskResult = Dts.Results.Success


    Catch ex As Exception

        Dim exceptionVariable As Microsoft.SqlServer.Dts.Runtime.Variables = Nothing
        Dts.VariableDispenser.LockOneForWrite("User::ScriptException", exceptionVariable)
        exceptionVariable("User::ScriptException").Value = ex.Message
        exceptionVariable.Unlock()
        Dts.Events.FireError(-1, "Task Name", ex.Message, String.Empty, 0)
        Dts.TaskResult = Dts.Results.Failure
     End Try

    End Sub