🤤

ASP.NET Core の Razor PagesとEntity Frameworkを触ったときの感触メモ

2024/01/25に公開

概要

これまでWPF案件が多かった中での初WEB開発で触れた技術なため
備忘録がてら感触のメモを残すことにする。
ただの感想文であり、ハウツーではないのであしからず。

Razor Pagesの感触

WPF/XAMLを刷り込まれて育った身としては、かなりしっくりきた。

なにが良かったか

CSHTMLファイルというHTMLと埋め込みタグで構成されているのは、非常にやりやすかった。
CMSやWPF/XAMLで長く開発してきたらとっつきやすいと感じた。

cshtml

@using XXX.EnumXXX
~省略~
<div class="www">
	@if(Model.DisplayData.XXX == (EnumXXX.XXX))
	{
		<span>AAA</span>
	}
	else
	{
		<span>BBB</span>
	}
	<span>@Model.DisplayData.YYY</span>
	<span>@Model.DisplayData.ZZZ</span>
</div>

cshtml.cs

public XXXclass DisplayData { get; set; }

public void onGet()
{
	DisplayData = new XXXclass();
}
~~~
public class XXXclass
{
	public string XXX { get; set; }
	public string YYY { get; set; }
	public string ZZZ { get; set; }
}

のような書き方などでプロパティの値を表示できて、直感的というかやりやすいと感じた。
WPFでは画面上の表示切り替え等をVM側でやるため、切り分けの点でアレなところ
(リアルタイムの制御となると、jQueryでDOMを取得して操作する手間なども)もあるが
なんというかJavaを捨ててもうこれで良いんじゃね?とさえ思った。
(経験則でJavaがイヤなだけ)

Entity Frameworkの感触

正直とっつきにくかった、学習コストが高い上に
メリット・デメリットがはっきり分かれる代物だと感じた。

テーブルの結合が見えやすい

テーブルAのXXX_IDを外部キーが、テーブルBのインデックスIDと紐づく
といったリレーションシップをプログラム上で定義できる。

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<YYY_Table>()
        .HasMany(e => e.YYYs) //YYY_Table内に同じIDのデータが複数いる
        .WithOne(e => e.XXX) //別所で定義された親テーブルYYYが1ついる
        .HasForeignKey(e => e.BlogId)
        .HasPrincipalKey(e => e.Id);
}

とはいえ予め定義しておけば、LINQで積み木のように組み立てていけるため
後続の作業者はラクできるなと思った。

余計なお世話機能が非常に厄介

テーブル同士の結合をミスると、勝手に謎カラム(XXX_ID1,XXX_ID2など)を生成して
謎SQLが出力されて、実行すると「そんなカラムは存在しない」エラーが発生する。
これで何度も手詰まりになった記憶が強い。
(こちらの方のブログがその辺を詳しく書いてくれています・・・)
https://jyuch.hatenablog.com/entry/2022/10/02/162005

LINQでSQLを組み立てられるのはやりやすいが・・・

単純なクエリでデータ取得だけならすごくやりやすい。

var list = await _dbContext.TX_XXX
	.Include(x => x.YYY) // XXXから子で結合しているテーブル
	.ThenInclude(y => ZZZ) //YYYから子で結合しているテーブル
	.Where(x => x.AAA == aaa)
	.Select(x => new {
		x.BBB,
		x.CCC,
		...
	})
	.ToListAsync();

のように、アプリ内の処理各所でSQL実行する場合などで
柔軟にSQLを組み立てれるのは非常に良いと感じた。

テクニカルな条件

ただしWhere句を条件によって変えたい場合は

  • Queryの状態でIF判定内でWhere()を足していく
  • 式木を利用してどちらかのWhere()を使用する
    など一工夫が必要で、このパターンを引いたときが困った。

Queryの状態でIF判定

var query = _dbContext.TX_XXX
    .Include(x => x.YYY);

if(hoge == fuga)
{
    query.where(x => x.aaa == x.yyy.bbb)
}

// aaaがbbbである条件が追加されたクエリが実行される
var result = await query.ToListAsync();

式木は全く理解できていないので割愛。
ブログを書いている方がいたためこちらを参照。
Expression Treeとは

また、上記ブログでも語られている

生成されたSQLの確認は必須

で、正直SQLクエリをEntity Frameworkで最適化するのは
難しい気がした。
その辺りも上記ブログで詳しく書かれているので参照。

Entity定義修正が頻発するとつらい

頻繁な仕様変更が発生する現場だったため、マイグレーションでカラム名や型が変わり
その都度修正が現場内で頻発して、最新ソースを取り込む度にエラーが発生した。
(周知徹底で収まる話ではあるが・・・)
仕様変更等で何度もDBの定義が変わると、都度Entityの定義修正が発生して
非常に面倒だった。
(リリース間際になっても仕様変更を言い出す"お客様"がいらっしゃいましたので)

N+1が発生しやすい

Entity Frameworkに限った話ではない上に、知識があれば未然に防げることであるが
実行速度が比較的遅いEntity Frameworkで、膨大な数のN+1をすると
クリティカルになりやすいため、気を遣う必要があるように感じた。

終わりに

あの現場はとても面白かった。
(みんな帰宅が0時回っていたけど)

Discussion