Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows azure blob storage from a SQL SSIS package

Is it possible to upload images to Windows azure blob storage from a SQL SSIS package? SSIS will read new images (on daily basis) from one of my on-Premise SQL Server (table) and upload images to blob storage.

like image 584
user2962182 Avatar asked Nov 06 '13 21:11

user2962182


1 Answers

What a fun question this was! I got to thread together a lot of pieces that I had never tried.

I first built out a simple console app based on the fine manual over on HOW TO: Blob Storage. Knowing that I had working code allowed me to adapt it for SSIS.

I created 3 SSIS Variables at the Package level. AccountName, AccountKey and ContainerName. They are all data type String. These provide credentials + the folder where my uploaded data will reside.

data flow and variables

Data Flow

The general look of your data flow is rather simple. A data source to a Script Component that will act as a Destination. You will need two columns: one provides a unique name for the blob and the other will be the binary bits.

My source is a trivial table. It has Country Names and their flag (stored as varbinary(max)) which you yourself can scrape from the CIA World Handbook if you're so inclined.

The Destination will be a bit of C#. Add a Script Component of type Destination.

On the Script tab, I have 3 ReadOnly Variables listed User::AccountKey,User::AccountName,User::ContainerName

On the Input Columns tab, I select CountryName and FlagImage.

The script itself follows. As noted in the How To, you will need to add a reference to Microsoft.WindowsAzure.Storage assembly before you can access the last 3 assemblies there.

using System;
using System.Data;
using System.IO;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

// Must add reference to Microsoft.WindowsAzure.Storage for this to work
// http://www.windowsazure.com/en-us/develop/net/how-to-guides/blob-storage/
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

/// <summary>
/// Watch me load data to Azure from SSIS
/// </summary>
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{

    /// <summary>
    /// The storage account used
    /// </summary>
    private CloudStorageAccount storageAccount;

    /// <summary>
    /// An entity to work with the Blobs
    /// </summary>
    private CloudBlobClient blobClient;

    /// <summary>
    /// Blobs live in containers
    /// </summary>
    private CloudBlobContainer container;

    /// <summary>
    /// blockBlob instead of a pageBlob
    /// </summary>
    private CloudBlockBlob blockBlob;

    /// <summary>
    /// This method is called once, before rows begin to be processed in the data flow.
    ///
    /// You can remove this method if you don't need to do anything here.
    /// </summary>
    public override void PreExecute()
    {
        base.PreExecute();
        string cs = string.Empty;
        string csTemplate = string.Empty;
        string accountName = string.Empty;
        string accountKey = string.Empty;
        string containerName = string.Empty;

        accountName = Variables.AccountName;
        accountKey = Variables.AccountKey;
        containerName = Variables.ContainerName;
        csTemplate = "DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}";
        cs = string.Format(csTemplate, accountName, accountKey);

        this.storageAccount = CloudStorageAccount.Parse(cs);
        this.blobClient = this.storageAccount.CreateCloudBlobClient();
        this.container = this.blobClient.GetContainerReference(containerName);
        this.container.CreateIfNotExists();
        this.container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });

    }

    /// <summary>
    /// For each row passing through, upload to Azure
    /// </summary>
    /// <param name="Row">The row that is currently passing through the component</param>
    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        string blobName = string.Empty;

        using (MemoryStream memStream = new MemoryStream(Row.FlagImage.GetBlobData(0, (int)Row.FlagImage.Length)))
        {
            this.blockBlob = this.container.GetBlockBlobReference(Row.CountryName);
            this.blockBlob.UploadFromStream(memStream);
        }
    }

}

Global Assembly Cache (GAC)

Assemblies you wish to use within SSIS must reside in the GAC. Assemblies cannot go into the GAC unless they are signed. Fortunately, the Azure assemblies are signed so from a Visual Studio Command Prompt, type gacutil -if "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.1\ref\Microsoft.WindowsAzure.Storage.dll" or the equivalent of where your version of that assembly exists

Load successful

And as proof, here's a shot from Azure Storage Explorer

blobs everywhere

like image 155
billinkc Avatar answered Nov 09 '22 22:11

billinkc