web-dev-qa-db-ja.com

エンティティフレームワークの1:1の関係で、関連付けの主な意味は何ですか

public class Foo
{
    public string FooId{get;set;}
    public Boo Boo{get;set;}
}


public class Boo
{
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

エラーが発生したときに、Entity Frameworkでこれを実行しようとしていました。

タイプ「ConsoleApplication5.Boo」と「ConsoleApplication5.Foo」の間の関連付けの主な終了を判別できません。このアソシエーションのプリンシパルエンドは、リレーションシップの流れるAPIまたはデータアノテーションを使用して明示的に構成する必要があります。

このエラーの解決策についてStackOverflowで質問を見ましたが、「プリンシパルエンド」という用語の意味を理解したいです。

260

1対1の関係では、一方の端がプリンシパルであり、もう一方の端が依存している必要があります。プリンシパルエンドは、最初に挿入され、依存するエンドなしで存在できるエンドです。依存端は、プリンシパルへの外部キーがあるため、プリンシパルの後に挿入する必要があるものです。

エンティティフレームワークの場合、依存するFKもそのPKである必要があるため、次のように使用する必要があります。

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

または流mappingなマッピング

modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Boo)
            .WithRequired(s => s.Foo);
368
Ladislav Mrnka

これを解決するために [Required] データ注釈属性を使用することもできます:

public class Foo
{
    public string FooId { get; set; }

    public Boo Boo { get; set; }
}

public class Boo
{
    public string BooId { get; set; }

    [Required]
    public Foo Foo {get; set; }
}

FooにはBooが必要です。

177

これは、1対1の関係を構成するための流れるようなAPIの使用に関する@Ladislav Mrnkaの回答を参照しています。

FK of dependent must be it's PKを使用することが不可能な状況がありました。

たとえば、Fooは既にBarと1対多の関係になっています。

public class Foo {
   public Guid FooId;
   public virtual ICollection<> Bars; 
}
public class Bar {
   //PK
   public Guid BarId;
   //FK to Foo
   public Guid FooId;
   public virtual Foo Foo;
}

ここで、FooとBarの間にもう1対1の関係を追加する必要がありました。

public class Foo {
   public Guid FooId;
   public Guid PrimaryBarId;// needs to be removed(from entity),as we specify it in fluent api
   public virtual Bar PrimaryBar;
   public virtual ICollection<> Bars;
}
public class Bar {
   public Guid BarId;
   public Guid FooId;
   public virtual Foo PrimaryBarOfFoo;
   public virtual Foo Foo;
}

Fluent APIを使用して1対1の関係を指定する方法は次のとおりです。

modelBuilder.Entity<Bar>()
            .HasOptional(p => p.PrimaryBarOfFoo)
            .WithOptionalPrincipal(o => o.PrimaryBar)
            .Map(x => x.MapKey("PrimaryBarId"));

PrimaryBarIdの追加中は、流れるようなAPIで指定するため、削除する必要があることに注意してください。

メソッド名[WithOptionalPrincipal()][1]は皮肉なことに注意してください。この場合、プリンシパルはBarです。 WithOptionalDependent() msdnの説明により、より明確になります。

5
Sudarshan_SMD