てぃぐれのプログラマwiki

ワクワクに従う

EntityFramework 多対多【C#】

経緯

Entity Frameworkで多対多を扱った記事が少なすぎる気がする。

というかSQLをごりごり書いていた身からすると、かなり扱いづらい。

たとえ記事があっても、Controllerでの記述方法が全然見つからない。

新人の子が多対多でデータを取得するのに一緒につまづくことにした。

 

つまづきポイント① キーがない

まず、リレーションテーブルには主キーが基本的にない。いや、複合主キー設定するという人もいるだろう。さて、主キーを設定したが、モデルクラスはどうすればいいのだろう。

複合主キーを設定してもしなくても怒られる。

キーの設定はDBに欲しいのではない。C#側に欲しいのだ。

dot Net Core (Entity Frame Core )の多対多リレーションの取得|プログラムメモ

 protected override void OnModelCreating(ModelBuilder modelBuilder)
{
 modelBuilder.Entity<CategoryMemo>().HasKey(bc => new { bc.MemoId, bc.CategoryId });
}

つまづきポイント② どこ基準でとればいいのかわからない

普通SQLを書く場合

select * from Category c

inner join CategoryMemo cm on cm.category_id = c.id 

inner join Memo m on m.id = cm.memo_id 

というようにとる(経験上)。

 

今回の場合のできあがるSQLは下記のようにしてとった。

select * from CategoryMemo cm

inner join Category cm on cm.category_id = c.id 

inner join Memo m on m.id = cm.memo_id 

 

中間テーブル基準(Model)で取得している。

違和感。。

取得方法の雰囲気は下記の感じ(うろ覚え)。

_context.CategoryMemo.Include(x => x.Categoty).Include(y => y.Memo).ToListAsync();

ちなみにIncludeはjoinの意味で使うようだ。

 

つまづきポイント③ どこでなにをキーにして結合しているかわからない

上記で、調子にのって、さらにその先まで取得しようとする。

_context.CategoryMemo.Include(x => x.Categoty).Include(y => y.Memo).ThenInclude(z => z.User)ToListAsync();

MemoIdをキーにして取得しようとしてエラーになる。Userが欲しいのであれば、Memoの中にあるUserIdで連携したい。

 

解決策

SQLで書こう。

SQLで書く良さは次回に記述。