tech.guitarrapc.cóm

C#, PowerShell, Swift, Unity, Cloud, Serverless Technical Update and Features

.NET Standard や .NET Core におけるAzureのStorage関連nugetパッケージの選択

Azure の C# 向け Storage SDK は nuget でサクッとアプリケーションに追加できます。

しかし、現時点ではWindowsAzure.Storage パッケージとMicrosoft.Azure.Storage.Xxxx パッケージに分かれており、お互いが干渉合うために混在するとAssembly Bindingsを含む解決まで手間取ることになります。

いくつかトラブルに遭遇してきた経験から、どんな時にどのパッケージを選ぶのが良いのか考えます。*1

目次

TL;DR;

WebJobs (AzureFunctions) を使う場合、WindowsAzure.Storage を使うのが安定でオススメ。

Microsoft.Azure.Storage を使う場合、WindowsAzure.Storage で使っているクラスと重複し、完全修飾名やdllレベルで一致させてもバージョンによって実行時エラーが起こります。

Azure の ストレージを扱うための nuget パッケージ

Azure では、もともとWindowsAzure.Storage nuget パッケージを使ってストレージ系の処理を提供していました。

https://www.nuget.org/packages/WindowsAzure.Storage/

しかしこのパッケージは、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 ページに記載があります。

https://blogs.msdn.microsoft.com/windowsazurestorage/

GitHub リポジトリ

WindowsAzure.StorageMicrosoft.Azure.Storage.Xxxx も、次のリポジトリで管理されています。

https://github.com/Azure/azure-storage-net

WindowsAzure.Storage と Microsoft.Azure.Storage の違い

GitHub や NuGet では情報が散乱しているのですが、Stack Overflow によくまとまっています。

  1. Microsoft.Azure.Storage splits libraries to three parts, Blob, Queue and File, which means we can install separate package instead of the full edition.
  2. Microsoft.Azure.Storage doesn't support Table API, it is transferred to Microsoft.Azure.CosmosDB.Table, which is only for .NET Framework right now.
  3. 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.
  4. Microsoft.Azure.Storage v9.4 package moves back to use Microsoft.WindowsAzure.Storage namespace temporarily to ease the transition for existing libraries.

https://stackoverflow.com/questions/53214947/what-is-the-difference-between-the-microsoft-azure-storage-and-windowsazure-stor

少し見ていきましょう。

.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.StorageMicrosoft.Azure.CosmosDB.Table で型定義を解決できない状況があります。おとなしく WindowsAzure.Storage を使うといいでしょう。

Minimum .Net Standard2.0 対応したいかどうかで判断する

この場合、Microsoft.Azure.Storage を使わざるを得ないでしょう。.NET Standard 1.3 でも .NET Standard 2.0 プロジェクトで利用はできるので、最小バージョンを 2.0 以上にしたいか次第です。

型合わせパズルにはまりたくないかで判断する

WindowsAzure.StorageMicrosoft.Azure.Storage を併用した場合に、型合わせ問題が起こるので結構排他感は残っています。

混在している場合に型合わせパズルをしたくないなら、現状では WindowsAzure.Storage に統一するのが安定しています。

Tips

Microsoft Azure Storage Common は直接参照して使うものではない

nuget パッケージには、https://www.nuget.org/packages/Microsoft.Azure.Storage.Common/ がありますがこれを直接 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

Entity定義のためにTableEntityを継承したクラスは利用プロジェクトとプロジェクト分離しない

守らないとつらい原則は一つです。

  • TableEntity の継承クラスは利用プロジェクトと異なるプロジェクトに定義しない

症状は実行時の初期化でアセンブリの解決がうまくいかず即死します。

  • 特定のマイナーバージョン同志で合わせる必要がある
  • 実行時にしか検査できない (Entity の初期化で死ぬのでアプリ実行時に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 がコミュニティからは期待されています。

https://github.com/Azure/azure-cosmos-dotnet-v2/issues/344

preview がとれたら、こちらを使いましょう。ダウンロードがびっくりするほど少なくて不安感が大きいのですが。

まとめ

Stack Overflow や GitHub Issue で現在まで複数件の同様のトラブルが報告されているので、一度は遭遇する印象があります。C# を使う中でも比較的つらいと感じるペインポイントが出ている印象です。

Microsoft の公式パッケージ、かつ Azureの中でももっとも使われやすい機能に関するSDKなので、言語的にもう少しトラブルが少ないと嬉しいと感じます。 混在しないようにパッケージシステムで防げたりするといいんでしょうね。

*1:昨日も苦労したためまとめることにしました