|
検索
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Visual Studio
Azure
ASP.NET Core
ライトニングトーク
Plone
Selenium
AJAX
C#
jQuery
JavaScript
SQL Server
ADO.NET Entity Framework
WebMatrix
LINQ
EFCore
TypeScript
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2026年 01月 2025年 12月 2025年 11月 2025年 10月 2025年 09月 2025年 08月 2025年 07月 2025年 06月 2025年 05月 2025年 04月 2025年 03月 2025年 02月 2024年 12月 2024年 11月 2024年 10月 2024年 09月 2024年 08月 2024年 04月 2024年 03月 2024年 02月 2024年 01月 2023年 12月 2023年 11月 2023年 10月 2023年 09月 2023年 08月 2023年 07月 2023年 06月 2023年 05月 2023年 04月 2023年 03月 2023年 02月 2023年 01月 2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 |
2017年 01月 20日
以前の投稿で、Azure Functions を活用することで、各種 Selenium WebDriver ファイルのバージョンアップを定期的に監視、メールで通知する、C# 実装による仕組みを作ったことを書いた。
Azure Functions を使って Selenium WebDriver の新バージョンリリースの通知を受け取る http://devadjust.exblog.jp/23744108/ さて、新バージョンリリースを検知するためには、それまで時点でわかっている最新バージョンをどこかに保存・永続化しておく必要がある。 新バージョンリリースのチェック実行時、
そのように最新バージョン番号を保存・永続化する具体的な手立てとして、安価で使い慣れている Azure Table Storage を採用したのであった。 そして前回投稿に書いたように、C# によるファンクション中から Azure Table Storage の読み書きを行うにあたっては、Azure Functions だからといって特別なことは何もない、いたって普通の C# による Azure Table Storage アクセスコードをゴリゴリと記述することで済ませていた。 しかし、である。 Azure ポータル Web サイト上での、Azure Functions の管理画面をいじっていると、入力 (Input) や出力 (Output) のバインディング(連携)先の選択肢に、"Table Storage" という選択肢が用意されているのだ。 ![]() ということで、Azure Functions が予め用意してある、Azure Table Storage との連携方法について調べてみた。 ...なお、先に断っておくと、本記事に記載の内容は、下記の公式ドキュメントサイトをなぞった内容が多くを占めているので、その点は悪しからず。 Azure Functions Storage table bindings https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-table 連携その1. Azure Table Storage のエンティティを引数にもらうまずは入力から。つまり、ファンクションの実行時に、(本稿は C# スクリプトでのファンクション実装を前提にしているので) Run 静的メソッドの引数に Azure Table Storage のエンティティ ( ≒ レコード ) を渡してもらえる、という連携だ。 Azure Functions は、Azure Table Storage の入力連携に関して、"条件に該当するエンティティを最大 n 件取得して引数に渡してもらう" など、いくつかのシナリオに対応している。 ここでは、予め決めておいた特定の 1 エンティティを引数に渡してもらう方法について記す。 とりあえずは何か適当なファンクション (タイマーで起動とか、手動で起動とか) がすでに作成済みであるとしよう。 ※以降では、タイマー起動のテンプレートで作成した既存のファンクションに対し、編集する例で示す。 function.jsonまずはファンクションの引数や戻り値をどう外部と連携させるかなどを設定している JSON ファイル「function.json」を編集する。※註: Azure ポータル Web サイト画面上からは、既定では "Standard editor" と称される GUI フォーム画面から function.jsonでの構成内容を編集可能となっている。しかし、この GUI フォーム画面は、本稿作成時点では不都合な振る舞いがあったりする (例えばここでの説明のように "読み取る最大件数" を省いて設定したい場合に、しかし GUI フォームの "Standard editor" では既定の "50" が再表示されてしまう、など) 。そのため、function.json をテキストとして直接編集する "Advanced editor" モードに切り替えて編集する (下図)。 ![]() {プロパティ名と上記記載例から概ねくみ取ってもらえると思うが、function.json にて、"1 エントリ" を特定する情報をすべて記載しているのがポイントだ。 上記例に基づき解説を加えると下記のとおりだ。
![]() run.csxさて次は、対する C# (スクリプト) の実装。まず、受け取るエンティティを表現するクラスを、run.csx の冒頭で記述する。 例えばこんな感じ。 public class FooBar {TableEntity クラスから派生する必要がないのは知らなかった。その代わり、PartitionKey と RowKey のプロパティは必須である。 あとは、function.json で指定した連携対象の Azure Table と同じ構造となるようにプロパティを備えれば OK だ。 あとは Run 静的メソッドの引数に、function.json で指定したのと同じ引数名で、先述のクラスの型を引数を受け取るようにすればよい。 public static void Run(以上で、
補足・感想なお、function.json で指定した条件に合致するエンティティが見つからない場合は、"Object reference not set to an instance of an object." という例外で落ちるようだ。このようなシナリオ ( 予め読み取り条件が固定の "特定の1エントリ" だけを参照したい ) では、エンティティの特定条件を function.json に宣言的に記述するだけで、C# コード上は Azure Table Storage にアクセスするコードを一切書かずに、いきなりエンティティにマッピングされたオブジェクトとして入手・参照できる。 これはかなりシンプルで便利だと思う。 先述のとおり、公式ドキュメントサイトを見るとわかるように、入力連携にはほかにもいくつか対応シナリオがある。 目的・要件と、Azure Functions 側で用意してあるシナリオ・連携方式が合致する場合は、効率よく記述できそうだ。 連携その2. Azure Table Storage にエンティティを追加する次いで出力。つまり、ファンクションの実行によって、Azure Table Storage にレコード追加される、という連携だ。 入力の例の場合と同様、何か作成済みのファンクションについて、話を進める。 function.jsonまずは function.json から。下記要領で連携方法の記述を追加する。 {コンテナへの接続文字列の指定と、エンティティ追加対象となるテーブル名までを function.json で指定しておく。 run.csx次いで C# コード (run.csx)。何はともあれ、対象 Table のエンティティを表すクラスを定義しておく。 ここは入力連携のときと同じ。 public class FooBar {そして Run 静的メソッドの引数なのだが、function.json 中、name で指定したのと同じ引数名で、ICollector<エンティティにマッピングするクラス> 型の引数を追加する。public static void Run(あとは、この引数に渡された outputTable に対し、Add メソッドを使ってエンティティを表すクラスのインスタンスを追加するコードを書けばよい。 public static void Run(こうすることで、引数 outputTable に追加されたオブジェクトが、function.json で指定した Azure Table へのエンティティとして追加される。 補足・感想1回の Run メソッド呼び出しでも、その Run メソッド中で繰り返し Add メソッドを呼び出して複数オブジェクトを追加すれば、追加したオブジェクトぶんの複数エンティティが Azure Table に追加される。なお、パーティションキー・行キーが重複するオブジェクト(エンティティ)を追加した場合は、Run メソッドを抜けたあと、ICollector<T> の引数に追加した内容をフラッシュするタイミングで、下記のような例外が発生するようだ。 Error while handling parameter outputTable after function returned:. Microsoft.WindowsAzure.Storage: 0:The specified entity already exists 感想としては、Azure Table Storage との接続処理などをこまごま C# コード側に明記しなくて済むので、うれしい印象だ。 では、更新はどうやるの?さて、ここまでのシナリオでは、エンティティを読み取るか、追加するかだけで、既存のエンティティを更新するシナリオがなかった。冒頭で紹介した公式ドキュメントサイトを見ても、本記事投稿時点では、なんと、 更新の方法について記載がない。 ということで、更新をやるにはどうしたらよいか、粘り強くネット上で検索してみた。 すると StackOverflow に有力情報のスレッドを見つけた。 Azure Functions Table Binding: How do I update a row? http://stackoverflow.com/questions/36792547/azure-functions-table-binding-how-do-i-update-a-row 上記スレッドによれば、ある程度は Azure Functions による連携支援はあるものの、基本的には従来通りの Azure Table Storage にアクセスする典型的なコードを記述するしかないとのことだ。 実際にやってみよう。 function.json例によって、とりあえず何かファンクションはある状況から開始するとして。function.json の記述はこうだ。 {出力連携のときとほぼ同じだが、"direction" (方向) の指定が "out" (出力) ではなく "in" (入力) になってることに注意。 run.csxそして C# コード (run.csx) 側であるが、まず冒頭に、Microsoft.WindowsAzure.Storage アセンブリへの参照が必要になる。#r "Microsoft.WindowsAzure.Storage"記述を短縮化するために、名前空間 Microsoft.WindowsAzure.Storage.Table も冒頭でオープン (using) しておこう。 using Microsoft.WindowsAzure.Storage.Table;で、先述の連携方法では、何からも派生させることは不要だったエンティティを表すクラスだが、この更新系の実装においては TableEntry からの派生が必要となる。 public class FooBar : TableEntity {そして Run 静的メソッド。functuon.json 中で指定した引数名で引数追加となるが、引数の型は CloudTable とする。 public static void Run(あとは、こうして引数に渡された CkoudTable オブジェクトに対し、Azure Table Storage の読み書き処理を記述するだけだ。 例えば以下のような感じ。 public static void Run( 補足・感想読み込みのみ、または新規追加のみの連携と比べると、抽象度がぐっと下がってしまい、"生の" Azure Table Storage 読み書きのコードとなってしまった。とはいえ、接続を開設して CloudTable オブジェクトを用意するところまでは書かずに済む。 まとめAzure Table Storage に対し「読むだけ」「追加するだけ」の場合は、Azure Functions が用意してくれている連携の仕組み ( バインディング ) により、ファンクションを実装する側はずいぶんとシンプルに書けるようになっていい感じである。いっぽうで、既存のエンティティを「更新」する仕組みはずいぶんと荒削りだ。 生々しい Azure Table Storage へのアクセスコードを書くしかないのが今日時点での実情である。 しかし先の StackOverflow のスレッドによれば、"These steps will get easier with our next release," とのこと。 今後の Azure Functions の進化・アップグレードにより、"更新" シナリオについてももっとシンプルな実装手段が提供されることが期待はできそうだ。 それまでの間は、Azure Table Stoarge に対し更新系の連携が必要な場合は、上記のとおり CloudTabel オブジェクトで連携する手法でしのぐのが無難そうである。 それでも接続文字列の取得からはじめてすべて自前で記述するよりはマシだろう。 以上、Azure Functions における Azure Table Storage バインディングのまとめとする。
by developer-adjust
| 2017-01-20 12:50
| .NET
|
ファン申請 |
||