AzureのC# 向けStorage SDKはnugetでサクッとアプリケーションに追加できます。
しかし、現時点ではWindowsAzure.StorageパッケージとMicrosoft.Azure.Storage.Xxxxパッケージに分かれており、お互いが干渉合うために混在するとAssembly Bindingsを含む解決まで手間取ることになります。
いくつかトラブルに遭遇してきた経験から、どんな時にどのパッケージを選ぶのが良いのか考えます。*1
概要
WebJobs (AzureFunctions) を使う場合、WindowsAzure.Storageを使うのが安定でオススメ。
Microsoft.Azure.Storageを使う場合、WindowsAzure.Storageで使っているクラスと重複し、完全修飾名やdllレベルで一致させてもバージョンによって実行時エラーが起こります。
Azure の ストレージを扱うための nuget パッケージ
Azureでは、もともとWindowsAzure.Storage nugetパッケージを使ってストレージ系の処理を提供していました。
しかしこのパッケージは、Storage Blob / Storage Queue / Storage File / Storage Tableなど各種ストレージ系処理をまとめてしまっておりBlobだけ使いたい、Queueだけ使いたいなどというときには大きいパッケージです。
そこで、Blob / Queue / Fileを個別のnugetパッケージとして分離された新しいSDKがMicrosoft.Azure.Storage.Xxxxxです。WindowsAzure.Storageの9.4.0からは個別パッケージで提供されています。
https://www.nuget.org/packages/Microsoft.Azure.Storage.Blob/
https://www.nuget.org/packages/Microsoft.Azure.Storage.Queue/
https://www.nuget.org/packages/Microsoft.Azure.Storage.File/
なお、Storage Tableは提供されておらず、これはMicrosoft.Azure.CosmosDB.Tableや
Microsoft.Azure.Cosmos.Tableで提供されています。
https://www.nuget.org/packages/Microsoft.Azure.CosmosDB.Table/
https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Table/
これをもって、WindowsAzure.Storageは現在Legacy SDKと呼ばれています。(CosmosDBへのサポートは2018年11月まで)
なお、Storage TeamsのBlogではこれはアナウンスされておらずWindowsAzure.StorageのNuGetページに記載があります。
GitHub リポジトリ
WindowsAzure.Storage、Microsoft.Azure.Storage.Xxxxも、次のリポジトリで管理されています。
WindowsAzure.Storage と Microsoft.Azure.Storage の違い
GitHubやNuGetでは情報が散乱しているのですが、Stack Overflowによくまとまっています。
- Microsoft.Azure.Storage splits libraries to three parts, Blob, Queue and File, which means we can install separate package instead of the full edition
- Microsoft.Azure.Storage doesn't support Table API, it is transferred to Microsoft.Azure.CosmosDB.Table, which is only for .NET Framework right now
- Microsoft.Azure.Storage added NetStandard2.0 target support since 9.4.0-preview, which supports synchronous methods wrapped over the asynchronous APIs. WindowsAzure.Storage on NetStandard only has asynchronous APIs
- Microsoft.Azure.Storage v9.4 package moves back to use Microsoft.WindowsAzure.Storage namespace temporarily to ease the transition for existing libraries
少し見ていきましょう。
.NET Standard の対応状況から判断する
Microsoft.Azure.Storage 9.4.2時点です。
Azure Storage Tableを使って、.NET Coreアプリを作る場合、Windows.Azure.Storageを使う必要があります。
| 機能 | WindowsAzure.Storage | Microsoft.Azure.Storage | Microsoft.Azure.CosmosDB.Table | Microsoft.Azure.Cosmos.Table |
|---|---|---|---|---|
| Blob | .NET Standard 1.3 | .NET Standard 2.0 | n/a | n/a |
| Queue | .NET Standard 1.3 | .NET Standard 2.0 | n/a | n/a |
| File | .NET Standard 1.3 | .NET Standard 2.0 | n/a | n/a |
| Table | .NET Standard 1.3 | n/a | なし (.NET Framework 4.5のみ) | .NET Standard 2.0 |
WebJobs / AzureFunctions を使っているかで判断する
WebJobs (Azure Functionsも中でつかっている) は、WindowsAzure.Storageを依存パッケージに含んでいます。
そのため、WebJobs / AzureFunctionsを使う場合は、WindowsAzure.Storageを参照するのが妥当です。
このとき、WebJobsのパッケージバージョンとWindowsAzure.Storageのバージョンは合わせておくとAssembly Bindingに遭遇せず済むので安定します。
Storage Table を使っているかどうかで判断する
WindowsAzure.StorageとMicrosoft.Azure.CosmosDB.Tableで型定義を解決できない状況があります。おとなしくWindowsAzure.Storageを使うといいでしょう。
Minimum .Net Standard2.0 対応したいかどうかで判断する
この場合、Microsoft.Azure.Storageを使わざるを得ないでしょう。.NET Standard 1.3でも .NET Standard 2.0プロジェクトで利用はできるので、最小バージョンを2.0以上にしたいか次第です。
型合わせパズルにはまりたくないかで判断する
WindowsAzure.StorageとMicrosoft.Azure.Storageを併用した場合に、型合わせ問題が起こるので結構排他感は残っています。
混在している場合に型合わせパズルをしたくないなら、現状ではWindowsAzure.Storageに統一するのが安定しています。
Tips
Microsoft Azure Storage Common は直接参照して使うものではない
nugetパッケージには、nugetがありますがこれを直接NuGetで参照してはいけません。これはGitHubでCommonパッケージのフォルダにいくとREADMEで確認できます。(なぜGitHubに.... これではVSなどでパッケージを導入する場合に気付くことは難しいと感じます)
The Microsoft Azure Storage Common SDK for .NET is referenced by Azure Storage Blob/Queue/File SDKs and Azure CosmosDB Table SDK and should not be referenced directly by your application.
https://github.com/Azure/azure-storage-net/blob/master/Common/README.md
エンティティ定義のためにTableEntityを継承したクラスは利用プロジェクトとプロジェクト分離しない
守らないとつらい原則は1つです。
- TableEntityの継承クラスは利用プロジェクトと異なるプロジェクトに定義しない
症状は実行時の初期化でアセンブリの解決がうまくいかず即死します。
- 特定のマイナーバージョン同志で合わせる必要がある
- 実行時にしか検査できない (エンティティの初期化で死ぬのでアプリ実行時に100%起こります)
この2点の特性から「今のバージョンが問題ないか」判断するのが難しく、パッケージバージョンを上げていくことへの障壁となります。NuGetパッケージバージョンを合わせるだけではだめなのが難しいところです。
複数プロジェクトでTableEntityの型定義をしたいときに、この問題を回避する方法はいくつか考えられます。
- インタフェースでの回避 : インタフェースを共有するプロジェクトで定義して、それぞれの利用プロジェクトで実装
- テンプレートでの回避 : T4や他テンプレートを使ってクラスを自動生成、参照させる
新しいcsprojなら.csを個別に参照かかずに済むのでテンプレートでの回避が可能ですが、トリッキーすぎます。 私はインタフェースで互換を担保するにとどめました。
Microsoft.CosmosDB.Table と Microsoft.Cosmos.Table の違い
現在、Microsoft.Azure.Cosmos.Tableは現在previewパッケージですが、CosmosDBに対応した .NET Standard 2.0バージョンです。
APIにも違いがありますが、 .NET Standardへの対応が為されていることからMicrosoft.Cosmos.TableのGAがコミュニティからは期待されています。
previewがとれたら、こちらを使いましょう。ダウンロードがびっくりするほど少なくて不安感が大きいのですが。
まとめ
Stack OverflowやGitHub Issueで現在まで複数件の同様のトラブルが報告されているので、一度は遭遇する印象があります。C# を使う中でも比較的つらいと感じるペインポイントが出ている印象です。
Microsoftの公式パッケージ、かつAzureの中でももっとも使われやすい機能に関するSDKなので、言語的にもう少しトラブルが少ないと嬉しいと感じます。 混在しないようにパッケージシステムで防げたりするといいんでしょうね。
*1:昨日も苦労したためまとめることにしました