modest violet

modest violet

開発者としてのあれこれや、日々の雑記など

your future hasn't written yet. no one's has.
by Emmett Lathrop "Doc" Brown

Visual Studioを使用中に「SQL Serverは動作を停止しました」が頻繁に発生する場合の対処法

特定の環境でVisual Studio 2015 または 2017 を使用していると、「sqlservr.exeは動作を停止しました」というメッセージボックスが頻繁に発生します。

現に私もこの現象に悩まされていました。一回一回のメッセージ表示は何ともないのですが、定期的に絶えず表示されるため、イライラが募るわけです。精神衛生上宜しくない。

原因はSQL Server Local Db

Visual Studioインストール時におそらくSQL Server Local Dbも一緒にインストールされているのですが、古いバージョンのLocal Dbがこのメッセージボックスの原因でした。

実際にSQL Server 2016 Express LocalDB に更新すると、今までのメッセージボックスが嘘のように、現象は回避されました。

インストール手順

下記のサイト様が大変判りやすく記載されています。

www.hiskip.com


自分の備忘録を兼ねて。。。

sqlservr.exe has stopped working

AutoMapper6でのプロファイル設定とユニットテスト

AutoMapperという自動マッピングライブラリーが便利なのです。ただ、少しばかり使い方を誤っていたようで、下記のサイトを参考に再勉強させて頂きました。

iyemon018.hatenablog.com

この記事のお陰で、今までの自分があまりにも恩恵を受けない無駄な記載をいっぱいしていたという事に気づきました。例えば、逆マッピングもわざわざ定義を書いていたとか、同じ名前のオブジェクトもわざわざ定義書いていたりだとか・・・。

いざ自分でも定義をプロファイル単位にしようと試していたのですが、どうも仕様が違っている様子・・・。
最新のAutoMapperは6.0.2になっており、プロファイルのオーバーライド辺りが変更になっていたようです。ですので、自分の備忘録も兼ねて手順を記載します。

マッピングの定義

以前のAutoMapperでは、Configure()メソッドをオーバーライドして定義を書いていましたが、バージョン6以降は互換がなくなったようで、コンストラクターに定義を記載する事になります。

public class HogeProfile : Profile
{
    // コンストラクターでマッピング定義を記載します
    public HogeProfile()
    {
        CreateMap<SourceClass, DestinationClass>()
            .ForMember(d => d.XXXXXXXXXX, o => o.MapFrom(s => s.YYYYYYYYYY))
            .ReverseMap()
            .ForMember(s => s.XXXXXXXXXX, o => o.MapFrom(d => d.YYYYYYYYYY))
            ;
    }
}


上記のように、必要な定義ごとにクラスを分ける方が管理しやすくて良いと思います。以前一つのクラスの中に定義をまとめて書いていたのですが、数が多くなると判りにくくて仕方が無いという経験からの意見です。

作成したプロファイル設定は、ASP.NET MVCであればGlobal.asaxなどに呼び出しの記述を行います。

Mapper.Initialize(config =>
    {
        config.AddProfile<HogeProfile >();
        config.AddProfile<HogeHogeProfile>();
    });

// マッピング設定の検証
Mapper.AssertConfigurationIsValid();

マッピングユニットテスト

基本的にそのまま値の受け渡しが行われるので、ユニットテストは不要という考えもできます。
但し、型が違うことによりAutoMapperで変換をかけたり、固定値を入れたりなど絶対不要か、といえばそうでも無いと思います。ユニットテストを書く癖をつけるためにも書いてみました。

簡単ですが、MSTestで書いたテストクラスはこんな感じです。

[TestClass()]
public class HogeProfileTests
{
    [ClassInitialize]
    public static void ClassInit(TestContext context)
    {
        Mapper.Initialize(config =>
        {
            // Global.asaxの呼び出し代わりにClassInitializeでプロファイルを呼び出しておく
            config.AddProfile<HogeProfile>(); 
        }); 
    }

    [TestMethod()]
    public void マッピング設定の検証()
    {
        // マッピングエラーならException
        Mapper.AssertConfigurationIsValid();
    }

    [TestMethod()]
    public void コピー元からコピー先へのマッピング検証()
    {
        var srcModel = new SourceClass()
        {
            // コピー元の値を適当に設定
        };

        var destModel = Mapper.Map<DestinationClass>(srcModel);

        // コピー元とコピー先で値が同じか
        Assert.AreEqual(destModel.xxxxxx, srcModel.xxxxxx); 

    //以下・・・省略
    
    }


    [TestMethod()]
    public void コピー先からコピー元への逆マッピング検証()
    {
        var destModel = new DestinationClass()
        {
            // コピー先の値を適当に設定
        };

        var srcModel = Mapper.Map<SourceClass>(destModel);

        // コピー元とコピー先で値が同じか
        Assert.AreEqual(srcModel.CategoryId, destModel.CategoryId);

        //以下・・・省略

    }
}


名前や型が同じプロパティー部分は比較検証しなくてもいいかな、というのが率直な感想です。
AutoMapperで何かしらのマッピング定義を施した箇所を中心にテストを作成するのが合理的だと思います。

Windowsの隠れた機能!実はメッセージボックスは○○○ができる!!

最終更新日時:2023.11.23

Windowsの歴史

上記の通り長い歴史があるWindowsです。私も長年Windowsに触れてきた訳ですが、まだまだ知らないこともたくさんあります。

つい最近も、偶然に知ったWindowsの機能に驚愕していたところです。本当に奥が深いよ、Windows

メッセージボックスに隠された機能

よくあるメッセージボックスです。これは、何かを書きかけている最中に閉じるボタンを押すと表示される「よく見かける」メッセージです。

この一見、何の変哲も無いメッセージボックス。

タイトル欄辺りをクリックして、メッセージボックスが選択されている状態にします。

そのまま、Ctrl + C キーを押してクリップボードにコピーします。

そして、適当なメモ帳などを新規で開いて、貼り付けを行うと・・・

[Window Title]
メモ帳

[Main Instruction]
無題 への変更内容を保存しますか?

[保存する(S)] [保存しない(N)] [キャンセル]


テキストとして、コピペができたんです!!


知っていました?かなり衝撃的だったんですけど・・・。

メッセージボックスでエラー内容とかいちいち見ながら打ち込んでたあの日は一体なんだったんだ!?と。


余談ですが、Excelのメッセージボックスではできませんでした・・・。パターンがあるのかな。

【Azure】Microsoft Cognitive ServicesのFace APIを検証したキロク

2017.03.28 大幅加筆しました。

f:id:shin21sk:20170327183607p:plain

Microsoft AzureにはCognitive Services(コグニティブサービス)といって、視覚や聴覚などAI技術を利用して認識を行う超絶便利なサービスがあります。

今回はその中で顔認識「Face API」を利用し、公式ドキュメントの曖昧な部分を検証しました。

Face APIに関しての詳細は、マイクロソフトの公式ドキュメント(英語)をご確認ください。

Microsoft Cognitive Services - Documentation

この通りに実装すれば、いとも簡単に顔認証ができます。本当に、Azureはヤバいです。

FaceAPI Freeプラン

FaceAPIにはFreeプランが存在します。ちょっとした評価や簡単な実装であれば問題ないのですが、少し本格的なサービスを実装しようとするとFreeプランのままでは制約が多いと感じました。
特に最初に判らないのは「トランザクション」の概念かと思います。

レベル 機能 料金
Face API - Free 1 分あたり 20 トランザクションまで 30,000 無料トランザクション / 月
Face API - Standard 最大 10 トランザクション/秒
0 - 1,000,000 トランザクション \153/1,000 トランザクション
1,000,001 - 5,000,000 トランザクション \112.20/1,000 トランザクション
5,000,001 - 20,000,000 トランザクション \66.30/1,000 トランザクション
フェイス ストレージ フェイス ストレージ - 各画像のサイズ上限は 4 MB 画像 1,000 枚あたり月額 - \51

出典
価格 - Face API | Microsoft Azure

ここで挙げられている「トランザクション」とは、何かしらの命令をFaceAPIに送る度にカウントされます。
例えば公式サンプルの記載では、顔認証完了までに最低3トランザクションが必要となっています。

using (Stream s = File.OpenRead(testImageFile))
{
    // 画像ファイルの認証 ->これで1トランザクション
    var faces = await faceServiceClient.DetectAsync(s);
    var faceIds = faces.Select(face => face.FaceId).ToArray();

  // 顔の認証 -> これで2トランザクション
    var results = await faceServiceClient.IdentifyAsync(personGroupId, faceIds);
    foreach (var identifyResult in results)
    {
        if (identifyResult.Candidates.Length == 0)
        {
            Console.WriteLine("No one identified");
        }
        else
        {
            var candidateId = identifyResult.Candidates[0].PersonId;

      // Person情報の呼び出し -> Loop毎にトランザクション数加算
            var person = await faceServiceClient.GetPersonAsync(personGroupId, candidateId);
        }
    }
}

これ以外にも、削除処理でも1件に付き1トランザクションとなりますので、不要なデータを削除したい場合でも注意が必要です。 

Freeプランでは、「1分間に20トランザクションまで」という制約がありますので、ちょっとしたサービスを構築するだけでもスグに上限値には達しそうです。

FaceAPIの階層構成

FaceAPIで写真を登録する場合、実際は3階層に分かれているのですが、サンプル通りに実装すると2階層までしか意識しなくても良い書き方となっています。お手軽に作成する分には何も問題はないのですが、原理を知りたいとか構成を知りたいとか行った場合には気になる所です。後述しますが、FaceAPIは「登録上限数」があるので、階層でどれくらい登録できるのか?は押さえておいて損はないと思います。
具体的には、「PersonGroup」「Person」「PersonFace」の3階層となっています。

f:id:shin21sk:20170328115410p:plain

1.PersonGroup階層

人物のグループを登録する為の階層です。認識の際は、このグループ内で合致する顔があるかどうかで検索が行われます。

最大1,000個のPersonGroupを作成する事が可能です。

PersonGroupには一意のpersonGroupIdが必要で、任意の文字列で登録することが出来ます。但し、使用出来る文字には制約があり数字、英字(小文字)、'-','_'が使用出来ます。特にこだわりがないのであれば、GUIDを作成しその値で作成すると良いと思います。

詳しくは、下記APIリファレンスを参照ください。
Microsoft Cognitive Services

2.Person階層

人単位のグループです。例えば、山田太郎さんの顔写真(複数)を管理する階層です。
新規登録時、PersonIdがGUIDで作成されます。同じ人物に画像を追加する場合はこのGUIDを保持しておく必要があります。

Person情報は、PersonGroup階層下に1,000ユーザー分作成可能です。1,000件を超えるとエラーとなる為、別グループへ登録する等の考慮が必要です。

3.PersonFace階層

人物の顔情報データです。(1画像毎に作成される)

一人の人物に対して、複数枚の画像を登録出来ます。理由としては、同じ人物に複数の顔写真を登録する事により、顔認証の精度が向上する事が可能な為です。
可能であれば、正面を向いた顔・側面・眼鏡の有無などの写真を登録すれば、より精度を高めることが出来ます。

但し、登録に際しては制約条件が数点あります。

  • 登録可能な数は1ユーザー毎に248件
  • 画像の種類は、JPEGPNG、GIF(最初のフレーム)、およびBMPがサポート
  • イメージファイルのサイズは、1KB以上4MB以下
  • 検出可能な顔のサイズは、36×36〜4096×4096ピクセル


特に写真で撮った画像をそのまま認証させたい場合など、画像サイズに注意が必要です。

削除時は下位層を考慮する

FaceServiceClientには各Deleteメソッドが準備されています。

例えば、PersonGroupを削除する場合は「DeletePersonGroupAsync」といった具合です。

但し、上位のPersonGroupを削除したとしても、下位層の「Person」「PersistedFace」は残ったままとなります。

よって、上位を削除する際には、下位層のデータを削除してから消すといった一手間が要りそうです。


削除も1件=1トランザクションで課金の対象となる為、敢えて残すという選択肢もあるとは思います。

値の無いデータは全てNotFoundでExceptionがスローされる

GetPersonGroupAsync等で指定した値に該当するデータが無い場合、nullでは無くExceptionがスローされます。

この辺りは善し悪しなのですが、個人的にはnullで返ってきてもらった方が慣れているので、一手間を加えて使用しています。

まとめ

もう何点か検証中項目がある為、随時更新していきます。

一つ言えるのは、Azure楽しい♪という事です。

未来を切り拓く勉強術:金子哲雄さんの言葉が教えてくれた大人の学び方

最終更新日:2023/11/24

学生時代は勤勉でもなんでもなく、どちらかというとノートを写させて貰う事のほうが多い、怠惰な学生だったと思います。
社会人になった後も、仕事の忙しさにかまけて自己啓発は無駄だと考えていた時期もありました。

そんな私ですが、今では勉強をしていないと何か落ち着かない気分になるので、不思議なものです。
とはいっても四六時中勉強なんて出来ませんので、隙間時間を有効活用するようになったという方が的確かもしれません。

色々と勉強に至るキッカケはあったのですが、「転職」が大きなきっかけだったと思います。

会社にとって自分は必須ではない

現役バリバリで自分しか出来ない事をやっていると「自分はこの会社にとって、必要不可欠な人材」「自分の代わりなんて誰もいない」と思いがちです。現に私もそう思っていた時期もありました。でも、その会社を辞めて、辞めた後の状況を聞いても大抵なんとかなっているんですよね。

自分は必要不可欠と思っていたのは自分だけであり、会社からしてみれば私は「必須」の存在ではなかった訳です。

『自分は特別ではない』
『自分の代わりは要る』

わりと衝撃的なこの事実。現にリストラが社会問題となった当時は、脱力する方も多かったようです。

この観点が私自身の勉強しなくては!という意志の開花につながりました。

書面での第一印象

『資格なんて実業務に使えないから取っても意味がない』という意見をよく聞きます。
確かに資格試験、特に情報処理系の資格はほとんど無意味な場合が多いです。

ですが、ある時ふと気付きました。
『未来永劫今の仕事で食べていけるという保証はどこにもない。』
『終身雇用なんてハナから期待していない自分にとって、ある日突然解雇されたら?』

自分には自分のスキルを客観的に評価出来る指標がない事に気付きました。そう、資格試験とはスキルを客観的に評価出来るツールだという事に気付けた訳です。
履歴書に資格欄が空白と記載有りなら印象が違います。年齢が上になればなるほどジワジワと効いてくる箇所です。

書面での第一印象で『客観的』に判断出来る資格試験の勉強へと繋がっていきます。

明日が来る事を当たり前と思わない

流通ジャーナリストで金子哲雄さんという方がおられました。2012年に肺カルチノイドという症例が非常に少ない病の為、41歳という若さでこの世を去られました。

私自身、この方がテレビによく出演されていた頃はあまりいい印象はなく、軽い内容を面白おかしく吹聴しているな、という認識でしかありませんでした。ですが、私の認識はお恥ずかしい限りで、金子哲雄さんは努力の塊のような人で、無くなる直前まで仕事を行い、自分のお葬式まで自分で手配・プロデュースしたのです。

この話を聴いた時、今までの認識を改め、尊敬の念を抱かずにはいられませんでした。

この本は、金子哲雄さんの死後に出版された手記です。

『自分が70歳、80歳の頃どうなっているかを前は想像していたのに、想像する事が出来なくなった』というニュアンスが非常に胸に刺さりました。

明日が来ることが当たり前に感じていますが、それはとても特別な事なんだという思いがひしひしと伝わってきます。

こんなに生を渇望している人がいる傍ら、私自身は毎日を無駄に浪費しているのではないだろうか・・・。

いつの頃からか、そう感じるようにもなりました。

「あの時こうしていれば」「この時こうだったら」と現在テレビで「東京タラレバ娘」というドラマをしているそうですが、「たられば」ばっかり言っていても仕方が無い訳です。
この世の中には生きたくても叶わず亡くなられた方が大勢いる。そんな人達に失礼のないように一生懸命生きなければ!というのが私が出した結論でした。

振り返れば、私自身の人生なんて一瞬の出来事です。
それも歴史には何の影響も与えないちっぽけな存在です。
だからといって、なんとなく日々を暮らすのはどうかなと。
ブログを始めたのも、今になって思えばそんな想いがあったからなのかもしれません。

『自分に出来ることを一生懸命やる』

そんな当たり前の事を大事にしていきたいと、金子哲雄さんの本をあらためて手にして感じた気持ちをそのまま書いてみました。