Azure Storage への接続方法が変わったので紹介します

以前少し書きましたが、November 2009 にて Azure Storage にアクセスする方法が SDK の Sample 付属の StorageClient プロジェクトから、Microsoft.WindowsAzure.StorageClient.dll に変更されました。
Windows Azure SDK November 2009 で dll の構成が変わってる! - お だ のスペース
Azure November 2009 への移行は手強い… - お だ のスペース


そのため、StorageClient を使用していたコードも修正する必要が出てきました。その変更点を紹介します。今回は、Queue について書きます。Blob や Table は未だ使ってませんが、きっと殆ど同じだと思います。
※これでも動くけど他の実装方法もあります。興味のある方は、November 2009 に付属している samples-cs に StorageClient を使用しているサンプルが幾つかあるのでそちらも確認してください。


まず、設定ファイル(.csdef、.cscfg)が変わります。今まで、AccountName、AccountSharedKey と別々に書いていたものが、一つに出来るようになりました。
また、各ストレージの EndPoint については、書かなくてもよくなりました。

変更前

<ConfigurationSettings>
  <Setting name="AccountName" value="hoge" />
  <Setting name="AccountSharedKey" value="〜" />
  <Setting name="QueueStorageEndpoint" value="http://hoge.queue.core.windows.net/" />
</ConfigurationSettings>

変更後

<ConfigurationSettings>
  <Setting name="HogeConnectionString" value="DefaultEndpointsProtocol=https;AccountName=hoge;AccountKey=〜" />
</ConfigurationSettings>

設定ファイルに Storage の情報を保存していますが、以前は特に気にせずこの情報を使えたのですが、変更後は使えなくなってました。
というわけで、以下のコードを WebRole や WorkerRole の OnStart メソッドに仕込んで下さい。*1

このコードは、November 2009 付属の samples-cs から拝借しました。Storage を使用しているサンプルでは、実装されていたと思います。
Storage を使用する場合に必須だと思われる*2ので、スニペット化しといたら便利だと思います。

#region Setup CloudStorageAccount Configuration Setting Publisher

// This code sets up a handler to update CloudStorageAccount instances when their corresponding
// configuration settings change in the service configuration file.
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
{
  // Provide the configSetter with the initial value
  configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));

  RoleEnvironment.Changed += (sender, arg) =>
  {
    if (arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
        .Any((change) => (change.ConfigurationSettingName == configName)))
    {
      // The corresponding configuration setting has changed, propagate the value
      if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
      {
        // In this case, the change to the storage account credentials in the
        // service configuration is significant enough that the role needs to be
        // recycled in order to use the latest settings. (for example, the 
        // endpoint has changed)
        RoleEnvironment.RequestRecycle();
      }
    }
  };
});
#endregion

アカウント情報。以前は、StorageAccountInfo というクラスでしたが、変更後は、CloudStorageAccount というクラスになります。

変更前

using Microsoft.Samples.ServiceHosting.StorageClient;

StorageAccountInfo account = StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration();

変更後

using Microsoft.WindowsAzure;

CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("HogeConnectionString");

キューの操作を行うクラス。以前は、QueueStorage というクラスでしたが、変更後は、CloudQueueClient というクラスになります。
※変更後の CloudQueueClient を生成している CreateCloudQueueClient() メソッドは、拡張メソッドです。CloudStorageAccount クラスのメソッドではありません。
また、RetryPolicy を生成する RegryPolicies の Retry系のメソッド名から、最後の N が取り除かれてます。

変更前

using Microsoft.Samples.ServiceHosting.StorageClient;

// account はアカウント情報で紹介した StorageAccountInfo インスタンス
QueueStorage queueService = QueueStorage.Create(account);
queueService.RetryPolicy = RetryPolicies.RetryN(2, TimeSpan.FromMilliseconds(100));

変更後

using Microsoft.WindowsAzure.StorageClient;

// account はアカウント情報で紹介した CloudStorageAccount インスタンス
CloudQueueClient queueService = account.CreateCloudQueueClient();
// RetryN -> Retry に変更されている。RetryExponentialN も RetryExponential に変更されている。
queueService.RetryPolicy = RetryPolicies.Retry(2, TimeSpan.FromMilliseconds(100));

キュークラス。以前は、MesseageQueue というクラスでしたが、変更後は、CloudQueue というクラスになります。また、Queue のメッセージの型は、Message クラス が CloudQueueMessage クラスに変更されています。

変更前

using Microsoft.Samples.ServiceHosting.StorageClient;

string name = "hoge";
bool exists;
// queueService はキューの操作を行うクラスで紹介した QueueStorage インスタンス
MessageQueue q = queueService.GetQueue(name);
bool res = q.CreateQueue(out exists);
q.PutMessage(new Message("HogeHoge"));

変更後

using Microsoft.WindowsAzure.StorageClient;

string name = "hoge";
// queueService はキューの操作を行うクラスで紹介した CloudQueueClient インスタンス
CloudQueue q = queueService.GetQueueReference(name);
q.Create();
q.AddMessage(new CloudQueueMessage("HogeHoge"));

全体を繋げるとこんな感じになります。※あくまでもサンプルなので、例外処理等は省いています。

変更前

using Microsoft.Samples.ServiceHosting.StorageClient;

StorageAccountInfo account = StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration();

QueueStorage queueService = QueueStorage.Create(account);
queueService.RetryPolicy = RetryPolicies.RetryN(2, TimeSpan.FromMilliseconds(100));

string name = "hoge";
bool exists;
MessageQueue q = queueService.GetQueue(name);
bool res = q.CreateQueue(out exists);
q.PutMessage(new Message("HogeHoge"));

変更後

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("HogeConnectionString");
CloudQueueClient queueService = account.CreateCloudQueueClient();
queueService.RetryPolicy = RetryPolicies.Retry(2, TimeSpan.FromMilliseconds(100));

string name = "hoge";
CloudQueue q = queueService.GetQueueReference(name);
q.Create();
q.AddMessage(new CloudQueueMessage("HogeHoge"));

*1:WebRole や WorkerRole というのは、RoleEntryPoint を継承したプロジェクト作成時に出来るクラス

*2:設定ファイルを使用しなかったら問題無い?