お米 is ライス

C#やらUnityやらを勉強していて、これはメモっといたほうがええやろ、ということを書くつもりです

EntityFrameworkCoreで整数とか日付とか以外のオブジェクトをフィールドに持つクラスをデータベースで管理したいときにやること

やりたいこと

例えば商品(Product)をデータベースで管理したくてかつ商品が会社(Company)の情報を持っていて欲しいとき。
つまりはクラスの入れ子になっているクラスをデータベース管理したいとき。
具体的に書くとこんなの

//商品クラス
public class Product
{
    public int ID { get; set; }
    public Company Maker { get; set; }
}

//会社クラス
public class Company
{
    public string Name { get; set; }
    public string Location { get; set; }
}

できない理由

これをこのままデータベースにマイグレーション(dotnet-ef migrations add hogehoge)しようとしても次のように怒られると思う。

The entity type 'Company' requires a primary key to be defined.
// Companyに主キーが無いぞ!出直してこい!!

これはCompanyというクラスを別のテーブルに突っ込んで管理しようとしてるからだ(と思う)が、わざわざそんなことしてくれんでもええのに……となる。

解決方法

要は別のテーブルにではなくProductのテーブルに突っ込んでくれればすむ話である。
EntityFrameworkCoreにはそのように指定する方法があって、次のようにすればよい

using Microsoft.EntityFrameworkCore;

public class Product
{
    public int ID { get; set; }
    public Company Maker { get; set; }
}

//この属性をつける
[Owned]
public class Company
{
    public string Name { get; set; }
    public string Location { get; set; }
}

親のテーブルに突っ込みたいクラスに「Owned」という属性をつけているだけである。
これを使うにはNugetとかでMicrosoft.EntityFrameworkCoreを入れておく必要がある。
こうすることによってProductのテーブルに「Maker_Name」とか「Maker_Location」とかのカラムが追加されてそこからMakerが読み取られるようになる。
Makerを別のテーブルに突っ込んでたりもしないので「Companyに主キーが必要だ!」とかも言われずにデータベースを作ることができる。