どうやったらタイトルがわかりやすくなるか考えたがどう説明したらよいかわからなかったので
暫定でつけました。
初心者なので
・こんな無駄なことする必要ない
・データベースの作り方が悪いだけ
などいろいろあると思いますが、EntityFrameWorkが自動で処理してくれたので
情報としてあげておくと何か別の用途で使えるかもということで上げておくことにしました。
結局どういうことかというと例えば
ParentクラスとChildクラスがあって、(テーブルもParentとChildの2テーブル)
Parentクラス内に男の子と女の子のListを作ってそれをリレーションとして定義するという感じです。
//こんな感じ でもこれでは動きません。
public class Parent{
public int ParentId;
public List<Child> Boys { get; set; } = new();
public List<Child> Girls{ get; set; } = new();
}
public class Child{
public int ChileId;
public string Name;
public int ParentId;
}
//以下はコンテキスト内
public DbSet<Child>? Child { get; set; }
modelBuilder.Entity<Child>()
.HasOne(c => c.Parent)
.WithMany(p => p.Boys)
.HasForeignKey(c => c.ParentId);
modelBuilder.Entity<Child>()
.HasOne(c => c.Parent)
.WithMany(p => p.Girls)
.HasForeignKey(c => c.ParentId);
つまり、男の子と女の子を同じテーブルに入れて、親からみたら登録、呼び出しは
Boys、Girlsを使えばよいという状態です。BoysとGirlsはゲッターとセッターでChildテーブルから自分でフィルターしたらよいのではと思いますが、それはなしですべてEntityFrameWorkに処理させる方法の説明になります。
結論からするとChildの派生クラスでGirlsとBoysを作ってやるとEntityFrameWorkがChildのテーブルにDiscriminatorというカラムを追加して処理してくれるみたいです。どうやら
https://learn.microsoft.com/ja-jp/ef/core/modeling/inheritance#table-per-hierarchy-and-discriminator-configuration
に書いてるらしいです。
これに従うと今回の例の場合
public class Parent{
public int ParentId;
public List<Boy> Boys { get; set; } = new();
public List<Girl> Girls{ get; set; } = new();
}
public class Boy :Child{
}
public class Girl : Child{
}
public class Child{
public int ChileId;
public string Name;
public int ParentId;
}
//以下はコンテキスト内
public DbSet<Girl>? Girls { get; set; }
public DbSet<Boy>? Boys{get;set;}
modelBuilder.Entity<Boy>()
.HasOne(c => c.Parent)
.WithMany(p => p.Boys)
.HasForeignKey(c => c.ParentId);
modelBuilder.Entity<Girl>()
.HasOne(c => c.Parent)
.WithMany(p => p.Girls)
.HasForeignKey(c => c.ParentId);
とするとテーブルはBoysテーブル、GirlsテーブルではなくChildテーブルができる形で、ParentからBoysに登録するとChildテーブルのDiscriminatorカラムにBoyという文字列付で登録され、呼び出すとやはりBoyという文字列が付いた行だけが取り出せます。
自分のソースからParentとChildに書き換えたのでもしかするとどこか置換ミスがあって動かないかもしれませんが、これが必要な方には簡単に修正できると思いますのでご勘弁を。