Pandora Pocket

IT系と日常系の備忘録。三日坊主。

DelegateでLINQのWhere条件を外から渡す

たまに使おうと思って度忘れしているのでメモ。

LINQを使ってデータを抽出する際にWHERE句を用いますが、同じデータソースに対してWHERE句の中身だけが異なるなんてことがあるかと思います。

それぞれメソッドを分けると冗長ですので、WHERE句だけ外部から渡したい。

こういう時はDelegateを使えば外部からラムダ式を渡せます。

ex)

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Func<int, bool> filter = f => (f % 2 == 0) && (f > 5);

var result = numbers.Where(filter);

f:id:Ovis:20210607223638p:plain

参考

NuGetパッケージの名前空間コンフリクト対策でextern aliasを利用する

業務アプリで利用しているSDKを更新していてはまったので覚書。

問題

今回 Microsoft.Azure.CosmosMicrosoft.Azure.Cosmos.Table をそれぞれ用いる構成なのですが、単純にNuGetパッケージをインストールすると、名前空間が衝突する箇所があり、

f:id:Ovis:20210524121125p:plain

エラー CS0433 型 'IndexingMode' が 'Microsoft.Azure.Cosmos.Client, Version=3.18.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' と 'Microsoft.Azure.Cosmos.Table, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' の両方に存在します

このようにエラーとなります。

解決策

.NETではこのように名前空間が衝突してしまう場合に、 externエイリアスという機能を利用して解決することができます。

DLLファイルだったら各DLLのプロパティでエイリアスを指定するらしいのですが、NuGetパッケージの場合はそういうことはできません。

この場合、csprojファイルに下記のように記載することで対応できます。

 <Target Name="ChangeAliasesOfAzureTables" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
        <ItemGroup>
            <ReferencePath Condition="'%(FileName)' == 'Microsoft.Azure.Cosmos.Table(エイリアス指定したいNuGetパッケージ名)'">
                <Aliases>AzureTable(エイリアス名)</Aliases>
            </ReferencePath>
        </ItemGroup>
    </Target>

あとは通常通り、

extern alias AzureTable;
using AzureTable::Microsoft.Azure.Cosmos.Table;

こんな感じでusingを記載してやれば、うまく回避することができます。

参考

Azure Functionsでサフィックスが「_EXTENSION_VERSION」のアプリケーション設定はスワップ対象外?

タイトルがすべて。

Azure Functions v2がEOLとなり、FUNCTIONS_EXTENSION_VERSION の値を ~2.0 としていたアプリがありました。
当然EOL状態を放置することはできないため、v3に対応する修正を実施し、開発環境では正常に動くことを確認。
本番に向けステージング環境にデプロイ後、FUNCTIONS_EXTENSION_VERSION の値を ~3 に変更したうえでスワップを実施しました。

が、ここで本番環境でエラーが発生することが発覚し、急遽再スワップを実施して戻すことに。

発生したエラーは下記の通り。

Could not load type 'System.IAsyncDisposable' from assembly 'System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

IAsyncDisposable がライブラリにないぞと。
該当の処理はawait usingステートメントでSQLトランザクションを行っており、少なくとも開発環境では正常に動いている。

なんぞこれはと悩んでいたのですが、ここでアプリケーション設定の FUNCTIONS_EXTENSION_VERSION の値が ~2.0 のままになっていることが発覚。
スワップ時はダブルチェックでスロット設定を確認していたのになぜ・・・?と調査したところ、こちらのIssueが。

Any app setting that ends with _EXTENSION_VERSION will be treated as slot setting. This behavior has been added a while ago prior to when we introduces capability for users to mark settings as slot settings.

_EXTENSION_VERSIONで終わるアプリケーション設定はスロット設定にチェックを入れている入れていないにかかわらず、スロット設定として扱われると。

このためスワップしたときに切り替わらなかったようです。

開発環境は直接設定の上デプロイしたため正常に動き、本番はスワップ元で設定後デプロイして実行したものの、この段階では設定が ~3 と正しかったためにこちらも問題なく稼働。

スワップしたものの上記理由により FUNCTIONS_EXTENSION_VERSION が 入れ替わらず、 ~2.0 のままだったために.NET Core 3.1から利用可能になった処理で躓いてしまったのが今回の問題だった模様。

検証

検証のためにFunctionsを作成。

スワップ先になるプロダクション環境。スロット設定は無し。
f:id:Ovis:20201206134306p:plain

ステージング環境。 f:id:Ovis:20201206134351p:plain

スワップ処理。
構成変更には FUNCTIONS_EXTENSION_VERSION が表示されているので変更されるように見える。
f:id:Ovis:20201206134656p:plain

スワップは正常終了。
f:id:Ovis:20201206135108p:plain

プロダクション環境のアプリケーション設定を確認すると、 WEBSITE_CONTENTSHARE の値は変わっているのに FUNCTIONS_EXTENSION_VERSION は変わっていない。
f:id:Ovis:20201206135529p:plain これは罠だ・・・。

MQTTHomeClientをプラグインで機能拡張できるように改良した

この記事で作っていたMQTTHomeClient。
MQTT Brokerから受け取ったTopicから処理を分岐させるんですが、ここで呼び出すWakeOnLANの処理をプロジェクト内で実装しています。
どうせ私しか使わないんでべたべた書いてもいいんですが、勉強がてらMQTTのクライアントの機能拡張をDLL追加でできるように改良してみました。

続きを読む

「Ok Google,パソコンの電源を入れて」 を実現したい(IFTTT、MQTT、Raspberry Piを用いる方法)

家で仕事をしているのですが、普段寝る前にはパソコンの電源を落としています。
朝起きて身支度をして、仕事部屋に行ってからパソコンの電源を入れて・・・よりはデスクの前に来た段階で電源が入っていてほしい。

というわけで、朝起きたときに枕もとのGoogle Assistantに「パソコン付けて」というだけで電源が入るようにしました。

続きを読む