.NET Core CLI の View / Controller の scaffold 機能を試す

Ruby on Rails で長らくアプリケーション開発をしてきたものとしては、Rails の Scaffold 機能はその利用頻度は場合によるものの、とても好きな機能でした。

もちろん自動生成コードは完璧ではないものの、コマンド 1 撃でまずは CRUD が動かせるというのは、まさに土台として嬉しい体験だったんです。

ASP.NET Core でも同じことはできるだろうか?

目標は Railsrails generate scaffold User name:string email:string で Model / View / Controller / Migration の全てが生成される感じです。

結論は、できません でした。

でも、ある程度のところはできた、というか C# で書くならこれぐらいがちょうどいいかという感じでした。どうちょうどいいかは後述。

aspnet-codegenerator

dotnet aspnet-codegenerator command | Microsoft Docs

これが、今回の話の中心であり、もはや上記のリンク見てもらえれば終わりです 😅

今回見る機能は公式のチュートリアルにも MacVS Code を使うサンプルで登場します(つまり WindowsVisual Studio を使わないケース)
Add a model to an ASP.NET Core MVC app | Microsoft Docs

はい、チュートリアルも見てもらえればもう書くことないです。

一応やってみる

モデルは自分で書く

チュートリアルの通り Movie class と MovieContext class を書きます。そう、Model 部分は手書きする必要があります。

ただ、チュートリアルでは Model も同じ project に入れていますが、Console app 等からも同じデータアクセスの仕組みを使いたい場合も多いと思うので、多くのケースでは project を分けるのではと思います。
そうなると、Rails の (full) scaffold のように Model や Migration も同じ project に作られてしまうよりは、Controller / View だけ Scaffold するのがちょうどいいように思います。

というか、私も Rails では Model はたいてい手書きしてた。

たくさん package が必要

ここで出てくるのが次ですね。

dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.SQLite
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

まじか、と思うのは SQLite を利用する前提なのに、 SqlServer の package も必要になることです。

これ、deploy 時にも省けないのだとしたら deploy の size に影響するし、single binary にするんであれば、そのまま膨れ上がらないかなと 🙄
別プロジェクトを作って上記を import し、そこから MVC project に向けて Scaffold というのも試してみたんですが、やはり MVC project にこの package 参照が無いと実行できませんでした。。うーん、やり方悪いのかなぁ。

コネクションの設定

Startupappsettings.json にコネクションの設定を。

ここに書いておくだけで、後で出てくる dotnet-ef コマンドも実行先の接続先をここから読んでくれるようです。なるほどなぁ。
ちなみに、MVC project で dotnet-ef を実行しない場合には、接続先設定を desing-time factory というので別途定義できます。Model 部分だけ別プロジェクトにするなら使えそう。
Design-time DbContext Creation - EF Core | Microsoft Docs

Scaffold 実行

dotnet aspnet-codegenerator controller -name MoviesController -m Movie -dc MvcMovieContext --relativeFolderPath Controllers --useDefaultLayout --referenceScriptLibraries

どういう Controller 名にするかとかは自動で設定する訳ではありません。デフォルトは自動にしてくれもいいような気もしますが、まあ Model と Controller を同じ名前にしてしまおうというのは、実際最初だけなんでこれでいい気がします。

この実行が終わると View / Controller が生成されます 🎉🎉🎉

後は DB を migration すれば起動できる

おなじみのこれですね。

dotnet ef migrations add InitialCreate
dotnet ef database update

やってみて

もっと手間取るかと思いましたが、さくっとできました。
最初はチュートリアルを探せてなかったので、自分でオプション試しながらやってましたが、最初からチュートリアル見てたら読んで終わりにしてたかも 😎

Win の Visual Studio だと、GUI でその辺もやってくれるんでしょうけど、コマンド勢でも同じようにできて嬉しいですね。

チュートリアルのコードの方がいいと思いますが、私が今回書いたコードも以下に置いてあります。
https://github.com/dany1468/dotnet_ScaffoldExample/tree/master

dotnet tools は local に入れてある。

Appendix: Rails console も欲しい人生だった

Rails で最高の体験の一つは Rails console だったわけですが、それを ASP.NET Core でもやろうとしてみました。が、現状は失敗しました。

どうしても TypeInitializationException が出てしまい dotnet-script からは EF Core の呼び出しができなかった。

SQLite / SQLServer、Wiin/Mac と複数環境で試してみたんですが駄目だったのですが、以下のテストケース見てると、ある時点では通っていたようなので、自分が悪いか、現時点だけかなぁという気がしています。
https://github.com/filipw/dotnet-script/blob/master/src/Dotnet.Script.Tests/TestFixtures/NativeLibrary/NativeLibrary.csx

この辺は、また調査する時間ができたら切り分けてみようかなと思います。

ただ、Rails console like なことができたとして、誰得なのかというのはある。割とさくっと console app 書いて試すとかが多いのかなぁと。けど、REPL が欲しい。。