.NET Framework のプロジェクトで EF Core の Scaffold を使いテストデータを投入する

昨年は .NET Core のプロジェクトだったので、特に苦労なく EF Core の Scaffold で既存の DB から Entity を生成し、それでテストデータを作成するというのができていました。(.NET Core で作成してはいるものの、既存の .NET Framework 主軸のプロダクトの、サブ的位置づけだったので、メインの DB 操作に EF Core をがっつり組ませることはできないので、テストで利用していた)

最近になり、.NET Framework のプロジェクトを見ており、「なにはなくともテストをバリバリ書ける環境を作るぞ!」ということで同じことを .NET Framework でもやってみました。

EF Core と .NET Framework

Supported .NET implementations - EF Core | Microsoft Docs

上記サイトの通り、.NET Framework であっても 3.1 までなら EF Core を利用できます。

サンプル

GitHub - dany1468/NetFrameworkEfCoreTest

SDK スタイルでプロジェクトを作っておくと、dotnet cli との親和性もいいのでオススメです。(私が Rider 使いなので、VS でこの辺どういう感じかわかりませんが)

SDK スタイル プロジェクトでのターゲット フレームワーク - .NET | Microsoft Docs

PS > dotnet new classlib --target-framework-override net48 -o TestData

後は、EntityFramework と Scaffold 用のライブラリを入れます。上述の通り、3.1 系までなので、3.1.14 が現時点では利用できる一番新しいバージョンです。

PS > dotnet add package Microsoft.EntityFrameworkCore.Design -v 3.1.14
PS > dotnet add package Microsoft.EntityFrameworkCore.SqlServer -v 3.1.14

続いて、いろいろコマンドラインで済ませたいので dotnet tools で dotnet-ef を入れます。もちろん local install で。

PS > dotnet new tool-manifest
PS > dotnet tool install dotnet-ef
PS > dotnet ef --version
Entity Framework Core .NET Command-line Tools
5.0.5

dotnet tools に関しては、私は特に気にせず新しいのを入れてます。あくまでビルドは生成に利用するプロジェクトの Framework version を見るのでツールの方は関係ないようです。

後は対象の DB に対して以下を実行するだけです。(以下は docker で動いている DB に向けている例です。{{}} の中は実際には埋めてください。)

PS > dotnet ef dbcontext scaffold \
  --context MainDbContext \
  --context-dir Data/Entities \
  --output-dir Data/Entities \
  -f "Server=host.docker.internal,14331;Database={{.DATABASE}};User Id={{.USER}};Password={{.PASS}};" \
  Microsoft.EntityFrameworkCore.SqlServer

サンプルプロジェクトではテーブルを個別に指定するようにしていますが、上記のコマンドであれば、全テーブルを一気に作成できます。

EF Core の 5 からは --no-onconfiguring があるので、生成される DbContextOnConfiguring に余計な warning が埋め込まれなくていいんですが、まあこれは仕方ない。

春の芽吹き

秋冬野菜が収穫も終盤に差し掛かり、春蒔きの時期にきた。種を植えて 1, 2 週間たち少しずつ芽が出たり、出なかったりしている。

タイム

f:id:dany1468:20210325091944j:plain

一緒にセロリとセージも蒔いたがそちらは出ていない。

ナス / ピーマン / スイスチャード

f:id:dany1468:20210325091949j:plain

果菜類とスイスチャードの種は、キッチンペーパーで発芽させた。これは今年始めてやってみたが、なんとか出てくれた。

苗床に移して苗にしていく。

絹さや

春蒔きのものを蒔いておいた。秋蒔きの分が一部雪でやられてしまったため。

芽が出たばかり。 f:id:dany1468:20210325092029j:plain

2, 3 日でまあまあ大きくなる。 f:id:dany1468:20210325092004j:plain

秋に蒔いた豆類

雪でやられた分もあるが、春になって鳥に葉がついばまれて枯れてしまった分もある。 f:id:dany1468:20210325092034j:plain

順調に育っている分は実ができつつある。 f:id:dany1468:20210325092009j:plain

雑草も順調に育ってきて、いよいよ春が来た感がある。

GCP の組織アカウントを作った (Cloud Identity)

1 年ちょっと前にも学習用に一度作っていたのだけど、12ヶ月のトライアルが終わったのと、当時使っていたドメインを使うのをやめたかったので作り直した。

ドメイン

Google Domains でさくっと安いのを取得。

Cloud Identity で組織アカウント作成

Cloud Identityで構築するCompute Engine 共有VPC | apps-gcp.com

前回も上記の記事を参考にしたが、今回も基本的には同じ手順でいけた。というより、GCP 側が手厚くなっていて、より迷う部分がなくなっていた。

最初に迷う点としては、最初の GCP projectの「IAMと管理」 にいくのに、とりあえず個人のアカウントでもなんでもいいので、GCP のプロジェクトを用意しておかなくてはいけないということぐらいか。(この辺は前回のメモもあったのだけど、アレ、どうすんだっけ?となった)

ドメインの所有権の証明に関しても、Google Domains の方でさくっと TXT レコードを追加して完了。前回はお名前.com でやっていて、やたらと確認に時間がかかった記憶があるが、数分とかからず確認が終了した。

チェックリスト

f:id:dany1468:20210323082152p:plain

組織アカウント作成後にコンソールを開くと、以下のような画面が表示されて、「チェックリスト」というものが現れる。

これは前回もあったのかもしれないけれど、順番にやっていくとフォルダ/プロジェクト構成や、ユーザーとグループ、それに対応する権限の割り振り方など、基本的な型が示されていて、すごく参考になった。

いちいちスクショを撮ったりしていたのだけど、以下にページとしてまとまっていた。

Google Cloud 設定のチェックリスト  |  ドキュメント

プロジェクトをロギングやモニタリング用に作成したり、その辺を共有 VPC に接続しているあたりは、自分の思っていたのとプロジェクトの扱い方が異なっていたので、面白かった。

保育所の作品展覧会でした

例年は(順序の前後はあれど)年度の最後のイベントは生活発表会のようなものがあった。

去年であれば年中と年長のクラスがお店のようなものをして(工作して作ったものを売る)それより小さいクラスの子供やその保護者がそのお店を回ったりするというイベントがあった。内容は毎年違うのかもしれない。

ただ、今年は COVID-19 でいろんなイベントが中止になったりしていたので、このイベントも無いかなぁと思っていたが、先生たちがいろいろ考えてくれて、子供と一緒には回れないが、子供が前日までに展示したものを保護者が見るという形式にして開催してくれた。

娘の通う保育所は、隣に廃校の小学校があり保育所とその体育館が通路でつながっている。なので、雨天の遊び場になったり、こうしてイベントも屋外でできないものは、屋内でという対応ができるようになっている。

今回の展覧会もその体育館で行われたので、とにかく大きなスペースに大きな展示がいくつもならぶという感じになっていた。

娘のクラスの作品

他にもこの年度で書いた絵や工作もかざってあったが、おそらく今回用に作成したメインの展示だけ。

f:id:dany1468:20210129103012j:plain

f:id:dany1468:20210129103034j:plain

これは、去年の秋の発表会で娘のクラスが演じた劇「おおきなかぶ」の 1 シーンを等身大(かそれより大きい)で再現したものになる。

少ない人数ながら、クラスの思い出を作品にするというのもお題としてすごくいいし、こんな大きな立体を作れるんだというのに驚かされた。

娘はドレスに別の素材も使っていたが、こんな器用なことができるんだなぁと。きっと家でも見せてくれようとしてるんだけど、ちゃんと見てあげられていないなと反省したり。

f:id:dany1468:20210129103434j:plain

これはメインの展示というよりはクラスでみんなが作っている LaQ。

大物は LaQ 大好きな男の子 1 名の手によるものらしいが、今年度の春夏は LaQ が全然うまく作れないと悩んでいたのを思い返すと娘も一度覚えたものは繰り返し作れるようになっていて成長を感じる。

うちはブロックは LEGO 主体なのだけど、LaQ も形が面白いものが作れていいなぁと思うようになってきた。

最近の娘っ子

  • 歌が好き
    • というよりは LIsa が好き。車の中とかで暇になると聞かせろとせがんでくるが、いつの間にか歌詞も覚えてしまっているので記憶力にびっくりする。
    • 最近は声真似もするようになってきた。
    • そういえば Switch 用のマイク買ったのにカラオケできてないな。
  • 有吉の壁が好き
    • 最低でも一度の放映を 3 回は繰り返してみる。TVer で見れる限り見る。
    • ただ、夫婦ともお笑い好きだし、僕も内P を何十回と通しで見るぐらい好きなので、有吉の壁も好きです。
    • でも好きな芸人が兼近ってのは違うんじゃないだろうかと思うが。。。僕の最近のお気に入りはトム・ブラウンです。
  • じぃじ、ばぁばが好き
    • 関東まで移動するのが難しいので、もう会えなくなって 1 年ぐらいになるけれど、週に何度も LINE でビデオ通話をしてる。
    • 基本はばぁばが相手をしてくれているけど、娘もばぁばも、その辺の会社員よりビデオカンファレンス慣れしているので、リモートでままごとを展開できる。
    • ばぁばは食事の用意をしながらでも相手をしてくれるし、娘もリモートというのを分かっているので、そこでばぁばの反応が多少薄くなっても気にしない。
  • その他
    • もう少しで自転車乗れそう?
    • クラスメイトが歯が抜けた子がちらほら出たらしく羨ましがっている
    • よく中耳炎になる(僕もなってた)
    • 数字がうまくなった
    • ひらがな・カタカナはそれなり。(でも展覧会でいろんな子が書いている字を見て、年相応だと分かった。いくつかの字が鏡文字になるのは共通しているようだ)
    • 花粉症発症確定。。。早すぎやしないか。。でも仕方ないよな、ここに住んでたら。。
    • 夜布団でライトを消すと、「今日楽しかったこと、悲しかったこと」を必ず聞いてくる。たまに友達とうまくいっていない話がでてくる。

保育所について

情勢を鑑みてというのもあるだろうけど、天気のいい日はよく外で遊ばせてくれているらしい。朝送っていくと、年長さんが縄跳びやってたりして元気だなぁと思う。

まだ一年あるが、保育所にはいい感情しか出てこない数年だった。

確定申告の申請書類を作り終わった

去年も一応やってはいるが、数カ月分だけだったので今年が初めて一年分やった年になる。

大変さ

なんとなく大変なイメージはあるが、自分の場合は白色申告だし、仕事的にも仕入れがあるわけでもなく、報酬も銀行に月に数回振り込まれるだけなので、実際は経費の計算をするぐらいしかない。

後は、年金やら保険会社やらから送られてくる書類の内容を転記していくだけ。計算も弥生の白色申告が全部やってくれるので、言われるがままである。(在宅で仕事をしているので)家賃や電気代も去年の段階で何%に設定するかは設定してあったので、月々の費用を入れただけで勝手に計算してくれた。

書類として持っていく人は添付するものを揃えたりするものとかを整えるとかもあるのかもしれないが、今年も e-Tax で済ませるつもりなので、物理的に、データとしてファイリングして終わった。

もうすぐインボイス制度も始まるので「課税事業者への登録が」とか考えることは増えていきそうな感じではあります。

買ってよかったもの

今年は出張もまったくできなかったので、経費にあげるものが本当に少なかった。一方でデスク周りは本格的に個人事業主として仕事を始めた年というのもあったので、多少揃えた。

椅子は弟からもらったものがあったので、大きくは机とキーボード。キーボードはたいてい Macbook のキーボードで満足していたので、なにげに 10 年以上ぶりに買った。机は初めて。

どちらも去年の冬から身体のふしぶしの痛みが強かったのの対策にも買ったが、まあ大きく改善はしていないもののいろんな姿勢が取れるという意味では良かったと思う。

経費以外

経費以外もいくつか。

後はこれに加えて中古の車を買ったのが特に大きい買い物だった。Mazda CX-5 (3, 4 年前に生産された)にしたのだが、これまで軽しか乗ってこなかったでいろいろ快適で驚いている。

生産年的に AppleCarPlay 対応ではなかったのだが、そこだけ対応のナビに変えてもらった。が、実はあまり使えていない。
運転席側のフロントガラスにいろいろと表示されるのはゲームっぽくて運転が面白い。

お仕事

平日日中はフルタイムで契約させてもらっている取引先があるので、仕事のメインはそちらになる。業態として COVID-19 でかなり影響を受けたにも関わらず契約は継続してもらえてありがたい。

その他にも妻づてや知り合いづてでスポットの仕事がちらほらあり、その辺があれば週末の午前中とかでやる感じ。久しぶりに Rails を使う仕事なんかもあって、ひさしぶりに Rails のキャッチアップをしたが、平日の仕事の方の改善にもつながったりしてよい影響があった。
どうしても一つのことばかりしていると視点や思考が凝り固まってしまうので、機会があれば今後もやっていきたい。

今年度

M1 Macbook Pro の 16inch が出れば、今の 2013 年モデルの Macbook を買い換えるかもなぁという感じ。

3D プリンタか木材の CNC ルーターとかにもチャレンジしてみたいなと思っているが、なかなかどれを買っていいのか分からず進まない。

勉強会がオンラインになって、地方民でも参加しやすくなったはずなのに、結局参加できていないので今年は参加していきたい。

ASP.NET Core で小さく Sass と ES6 を使う

「小さく」と書いた理由には、その対比として Webpack のような Node のエコシステムを使った手法を置いている。つまり、そちらを「大掛かり」としている。

フロントエンドエンジニア不在の現場でフロントと向き合う

ASP.NET Core 関連のブログ等を読んでいたり、ASP.NET Core の SPA サポートをみていても、おそらく大きな流れとしては Node を素直に利用して、フロントはフロントの文化の中で開発しようというものに見える。

一方で、React / Vue などを使ったフロントエンド開発は、ASP.NET (MVC or WebForm) + jQuery の開発を主とする組織においてはハードルが非常に高い。

「勉強すれば」という声も聞こえてきそうだが、現実としてそういう組織は開発リソースも潤沢ではないため、学習しながら開発というのは難しく(しかも全く別分野のものを!)、当然フロントエンドエンジニアを採用するということも難しい。

ほとんど言い訳ではあるが、こういう背景があるという前提がある。

それでも JS / CSS の開発をアップデートしたい

SPA とまでいかなくとも、UI / UX に関する事業としての要望は上がっていくので、jQuery や普通の JavaScript を使うにしても、少しでも開発生産性を上げるようにしたい。

というところで、今回は最低限として以下を目指す。

  • JS/CSS のライブラリ管理できる(npm は使わない)
  • ES6 が使える(それ以上は望まない。でもアロー関数や class ぐらいは使いたい。)
  • Sass/Scss が使える

ライブラリ管理 Libman

Client-side library acquisition in ASP.NET Core with LibMan | Microsoft Docs

今回の要望を満たすのにちょうどいい。

dotnet tool も提供されている。

> dotnet tool install microsoft.web.librarymanager.cli

以下のようなコマンドでインストールができる。wwwroot 内のどこに配置するかも決められる。

> dotnet libman install jquery

インストールされたものは libman.json に記録されるため、それがある状態であれば以下で復元ができる。

> dotnet libman restore

ES6 / Sass の導入

Compilation of LESS, Scss, Stylus, JSX, ES6 and (Iced)CoffeeScript files

README の上記を見てもらって分かる通り、いくつかの形式をサポートしている。ただ、nuget の最終更新日 (2019 年で止まっている)を見てもらっても分かる通り、あまり活発ではなく、ES6 以上の対応は望めない。よって、さらにモダンな JS を使いたい場合は Webpack を使うしか無い。(TypeScript 等も当然そちらになる)

WebCompiler には以下のように dotnet tools も存在している。

GitHub - excubo-ag/WebCompiler

ただ、今回は極力開発体験として、IDE から実行ボタンを押せば済むだけにしたかったので MSBuild と連携して実行してくれる BuildWebCompiler の方を選択した。

以下が設定ファイルであるが、単に対応関係を書けばいいだけである。dotnet tools の方はフォルダ指定もできるので、この辺の設定を省略できるので、現場によっては dotnet tools を選んでもいいだろう。

[
  {
    "outputFile": "wwwroot/css/site.css",
    "inputFile": "wwwroot/css/site.scss"
  },
  {
    "outputFile": "wwwroot/js/site.js",
    "inputFile": "wwwroot/js/site.es6"
  }
]

上記を見て分かる通り、ES6 の場合は .es6 拡張子にしておく。(ここは例えば .es6.js とかにしてもいいが、IDE 側でうまくツリー表示してくれなかったので、素直に es6 にした)

bundler の導入

JS / CSS を bundle (及び minify )したいので、そちらも導入する。(WebCompiler でも minify はできるが、こちらでまとめて行うのであえてしていない)

こちらは Microsoft Docs に紹介があるので、詳細はそちらに譲るが、bundleconfig.json にまとめるファイルと出力ファイルを定義するだけなので迷う部分はない。

こちらも、MSBuild と連携してビルド時に実行してくれるため、開発体験としては、SCSS や ES6 を修正すると、ビルド時に CSS / JS への変換と、ファイルの bundle, minify をしてくれる感じになる。

当然、開発中は bundle と minify はいらないので、その辺は Release ビルド時だけ実行するように最適化できるとなお良さそうではある。

(テンプレートを使っている場合) bootstrap sass を使う

Sass を利用するようになったので、せっかくなので bootstrap sass を利用する。以下のように bootstrap.scss を用意し、lib 配下の bootstrap には sass フォルダもあるので、そこから必要なものだけインポートする。MVC テンプレートを使った場合の最低限だと以下のようになると思う。

@import '../lib/bootstrap/dist/scss/functions';
@import '../lib/bootstrap/dist/scss/mixins';
@import '../lib/bootstrap/dist/scss/variables';
@import '../lib/bootstrap/dist/scss/root';
@import '../lib/bootstrap/dist/scss/reboot';
@import '../lib/bootstrap/dist/scss/grid';
@import '../lib/bootstrap/dist/scss/navbar';
@import '../lib/bootstrap/dist/scss/utilities';
@import '../lib/bootstrap/dist/scss/type';

これを利用すれば、bootstrap.min.css を利用するよりサイズを削減できる。

_Layout.cshtml で分離させる

    <environment names="Development,Docker">
        <link rel="stylesheet" href="~/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment names="Staging,Production">
        <link rel="stylesheet" href="~/css/bootstrap.min.css" asp-append-version="true" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>

Microsoft Docs にも書いてあるが、同じようにする。(Sass で最低限だけ入れているので CDN からは読んでいない)

IDE 上でどう見えているか

f:id:dany1468:20210110003922p:plain

Rider での表示であるが、minify されたファイルも含めてツリー表示される。

最後に

今回の構成だと、JS のテストを書いたりというところまではいけていないし、おそらくは既存 jQuery / CSS での開発をちょっと便利にするぐらいにはなると思う。

なんとか Webpack を導入しつつも、既存の Web Form の開発者がそれを意識せずに開発できるようにというところを目指したかったが、おそらく綻びもでてしまうし、そこで開発体験が悪くなっても仕方がないので、フロントエンドの知見や人員が少しでも増えたところでという折り合いをつけようとしている感じ。

コード

GitHub - dany1468/aspnetcore_es6_sass

参考

他に検討したもの

以下はもう少し検討しても良かったのですが、Microsoft Docs で BuildBundlerMinifier が紹介されており、導入に関して説明がしやすいだろうというのがあったためというのが大きいです。

Cloud Build で Secret Manager で展開した環境変数を Docker の build-arg に渡す

Cloud Build で Secret Manager から接続情報を取得し、Github Packages の nuget feed からパッケージを復元する - dunno logs

先日上記のように Cloud Build で Secret Manager から取り出した値を環境変数として展開し、後続のビルドステップで利用するということをしましたが、 docker build するケースもあったのでついでに。

もはや Secret Manager は関係ない。

今回のファイル

Dockerfile

FROM alpine

ARG GITHUB_USER="test"
ARG GITHUB_TOKEN="token"
RUN echo $GITHUB_USER

alpine にしてますが、環境変数が渡されてるか知りたいだけなので、そこに意図はないです。

cloudbuild.yaml

steps:

- name: gcr.io/cloud-builders/gcloud
  entrypoint: bash
  args: 
  - -c
  - |
    gcloud secrets versions access --secret=github-access-token latest > /workspace/build_vars

- name: 'gcr.io/cloud-builders/docker'
  entrypoint: 'bash'
  args:
  - -c
  - |
    source /workspace/build_vars
    docker build --build-arg GITHUB_USER=$$GITHUB_USER --build-arg GITHUB_TOKEN=$$GITHUB_TOKEN .

Secret Mangar からの読み出しは変わってません。

docker build の部分が今回のポイントです。

以下に記述があるのですが、 $ 一つだと、Cloud Build の変数置換機能で期待通り評価されないので、 $$ としています。 Substituting variable values  |  Cloud Build Documentation

これでうまくいきます。

少し思うこと

Cloud Build には Substitution があって、外から値を与えられるのでそこに Secret Manager から値を渡せると嬉しいのだけどなぁと思いつつ、Sustitution の値はビルドログにもガッツリ残るしそこは微妙なのかもと。

KMS で暗号化した値を Substitution に渡して、それを中で復号するというのも検討してみたんですが、結局こちらに落ち着きました。

参考リンク