1. ホーム
  2. c#

[解決済み] Entity Framework Fluent APIを用いた1対1のオプション関係

2023-07-05 04:54:59

質問

Entity Framework Code Firstを使用して、1対1の任意の関係を使用したいと思います。2つのエンティティがあります。

public class PIIUser
{
    public int Id { get; set; }

    public int? LoyaltyUserDetailId { get; set; }
    public LoyaltyUserDetail LoyaltyUserDetail { get; set; }
}

public class LoyaltyUserDetail
{
    public int Id { get; set; }
    public double? AvailablePoints { get; set; }

    public int PIIUserId { get; set; }
    public PIIUser PIIUser { get; set; }
}

PIIUser を持つことがあります。 LoyaltyUserDetail がありますが LoyaltyUserDetail には、必ず PIIUser . これらの流動的なアプローチ手法を試してみました。

modelBuilder.Entity<PIIUser>()
            .HasOptional(t => t.LoyaltyUserDetail)
            .WithOptionalPrincipal(t => t.PIIUser)
            .WillCascadeOnDelete(true);

この方法では LoyaltyUserDetailId に外部キーを作成しません。 PIIUsers テーブルの外部キーです。

その後、以下のコードを試してみました。

modelBuilder.Entity<LoyaltyUserDetail>()
            .HasRequired(t => t.PIIUser)
            .WithRequiredDependent(t => t.LoyaltyUserDetail);

しかし、今回EFはこれら2つのテーブルに外部キーを作成しませんでした。

この問題に対して何かアイデアはありますか? どのようにエンティティフレームワークフルエントAPIを使用して1対1の任意の関係を作成することができますか?

どのように解決するのですか?

EF コードファーストのサポート 1:11:0..1 の関係があります。後者はあなたが探しているものです ("1対0または1")。

あなたの流暢な試みは次のように言っています。 両端が必要 であり は両端が任意 である。

必要なものは 任意 を片方に、そして が必要です。 があります。

Programming E.F. Code Firstの本からの例です。

modelBuilder.Entity<PersonPhoto>()
.HasRequired(p => p.PhotoOf)
.WithOptional(p => p.Photo);

PersonPhoto エンティティには、ナビゲーションプロパティとして PhotoOf を指す Person 型になります。 は Person タイプには、ナビゲーションプロパティとして Photo を指す PersonPhoto 型を指す。

関連する2つのクラスで、それぞれの型の 主キー ではなく 外部キー を使うことはありません。 LoyaltyUserDetailId または PIIUserId プロパティを使用します。その代わり、関係は Id フィールドに依存します。

上記のようにfluent APIを使用している場合、"co "フィールドに LoyaltyUser.Id を外部キーとして指定する必要はなく、EFがそれを判断します。

だから、自分自身をテストするためにあなたのコードを持っていない(私は頭からこれを行うのは嫌だ)... 私はこれをあなたのコードに次のように変換します。

public class PIIUser
{
    public int Id { get; set; }    
    public LoyaltyUserDetail LoyaltyUserDetail { get; set; }
}

public class LoyaltyUserDetail
{
    public int Id { get; set; }
    public double? AvailablePoints { get; set; }    
    public PIIUser PIIUser { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<LoyaltyUserDetail>()
  .HasRequired(lu => lu.PIIUser )
  .WithOptional(pi => pi.LoyaltyUserDetail );
}

LoyaltyUserDetailsと書いてありますね。 PIIUser プロパティは 必須 で、PIIUserの LoyaltyUserDetail プロパティは任意です。

反対側から始めてもいいのでは?

modelBuilder.Entity<PIIUser>()
.HasOptional(pi => pi.LoyaltyUserDetail)
.WithRequired(lu => lu.PIIUser);

となっていますが、これは PIIUser の LoyaltyUserDetail プロパティはオプションで、LoyaltyUserの PIIUser プロパティは必須です。

常にHAS/WITHのパターンを使用する必要があります。

HTHと参考までに、1対1(または1対0/1)の関係は、最初にコードで構成する際に最も混乱する関係の1つなので、あなただけではありません! :)