かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

UWPでEntity Framework OneToOne

先日OneToManyやったので今日はOneToOneをやってみたいと思います。

こんな感じのクラスを定義します。

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public PersonDetail Detail { get; set; }
}

public class PersonDetail
{
    public int Id { get; set; }
    public int Age { get; set; }
    public int PersonId { get; set; }
    public Person Person { get; set; }
}

そしてDbContextを以下のような雰囲気で定義します。HasOne, WithOne, ForeignKeyのパターンです。何故かForeignKeyにはラムダ式を指定するオーバーライドもあるのですがエラーになったので型と列名を指定するオーバーライドを使ってます。

public class SampleContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<PersonDetail> PersonDetails { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite("filename=sample.db");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        var people = modelBuilder.Entity<Person>();
        people.ToTable("People");

        var personDetails = modelBuilder.Entity<PersonDetail>();
        personDetails.ToTable("PersonDetails");
        personDetails.HasOne(x => x.Person)
            .WithOne(x => x.Detail)
            .HasForeignKey(typeof(PersonDetail), nameof(PersonDetail.PersonId))
            .OnDelete(Microsoft.Data.Entity.Metadata.DeleteBehavior.Restrict);
    }
}

こんな感じで実行できます。

// データ突っ込む
using (var ctx = new SampleContext())
{
    ctx.People.Add(new Person
    {
        Name = "Tanaka",
        Detail = new PersonDetail
        {
            Age = 30
        }
    });
    ctx.SaveChanges();
}

// データとってくる
using (var ctx = new SampleContext())
{
    var p = ctx.People.Include(x => x.Detail).First();
    Debug.WriteLine($"{p.Name} {p.Detail.Age}");
}