読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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}");
}