Search code examples
sql-serverazuressisazureservicebusscript-task

Connecting to Azure Service Bus from SSIS


I need to put a message into an Azure ServiceBus queue from an SSIS package running under SQL Server 2014. As suggested in this post: connecting to azure service bus queue from ssis, I wrote a Script Task that references the "Azure SDK 2.9". This approach has worked for me with Azure Storage Accounts to work with blobs (referencing the Microsoft.WindowsAzure.Storage assembly), but it is NOT working for the Azure Storage Bus (referencing the Microsoft.ServiceBus assembly). Any calls I make into that assembly trigger a Run-time exception: "exception has been thrown by the target of an invocation: at System.RuntimeMethodHandle.InvokeMethod(...)" When I comment out all calls to the Microsoft.ServiceBus assembly it runs fine, so it is obviously something about the assembly reference (version 2.4). I tried updating to the latest version with NuGet (version 3.0) and that made no difference.

So my question is: has anybody been able to place a message in an Azure Service Bus queue from SSIS, and if so, how did you do it?

Since somebody will ask for my Script Task code, I'm posting it:

#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
#endregion

#region CustomNamespaces
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
#endregion

namespace ST_dba6519c1eda4e0c968485a6eb7a6c29
{
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {
        public void Main()
        {
            try
            {
                // Create the message for the Queue
                string ClientShortName = Dts.Variables["$Package::ClientShortName"].Value.ToString();
                bool bExtendedForecast = (bool)Dts.Variables["$Package::ExtendedForecast"].Value;
                var msg = new BrokeredMessage(ClientShortName + ": ExtendedForecast=" + bExtendedForecast.ToString());  // this statement throws the exception

                // get Service Bus Connection Information from the Package Parameters
                string SBAccessKey = Dts.Variables["$Package::ServiceBusAccessKey"].Value.ToString();
                string SBNamespace = Dts.Variables["$Package::ServiceBusNamespace"].Value.ToString();
                string SBQueue = Dts.Variables["$Package::ServiceBusQueueName"].Value.ToString();
                String connStr = "Endpoint=sb://" + SBNamespace +
                        ".servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=" + SBAccessKey;

                // First Method tried
                Uri SBUri = ServiceBusEnvironment.CreateServiceUri(String.Empty, SBNamespace, String.Empty); // this statement throws the exception
                TokenProvider SBToken = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", SBAccessKey);
                NamespaceManager nsMgr = new NamespaceManager(SBUri, SBToken);
                MessagingFactory msgFactory = MessagingFactory.Create(nsMgr.Address, nsMgr.Settings.TokenProvider);
                QueueClient queueClient2 = msgFactory.CreateQueueClient(SBQueue);
                queueClient2.Send(msg);

                // Second Method tried
                MessagingFactory factory = MessagingFactory.CreateFromConnectionString(connStr); // this statement throws the exception
                MessageSender queueSender = factory.CreateMessageSender(SBQueue);
                queueSender.Send(msg);

                // Third Method tried
                QueueClient queueClient = QueueClient.CreateFromConnectionString(connStr, SBQueue); // this statement throws the exception
                queueClient.Send(msg);

                Dts.TaskResult = (int)ScriptResults.Success;
            }
            catch
            {
                Dts.TaskResult = (int)ScriptResults.Failure;
            }
        }
        #region ScriptResults declaration
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion
    }
}

Solution

  • So, of course 10 minutes after I post the question, I hit upon the answer. I had to run GACUTIL -i Microsoft.ServiceBus. Once that was done, I chose to use the Third Method in the code (the simplest) to Send the message, and it worked fine.