ASP.NET Core の Razor PagesとEntity Frameworkを触ったときの感触メモ
概要
これまで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が出力されて、実行すると「そんなカラムは存在しない」エラーが発生する。
これで何度も手詰まりになった記憶が強い。
(こちらの方のブログがその辺を詳しく書いてくれています・・・)
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