29

背景については、次の投稿を参照してください。

ナビゲーション プロパティのないエンティティ フレームワークの 1 対 0 または 1 の関係

ForeignKeyクラス内のどのプロパティがナビゲーションプロパティを決定するForeignKeyを保持しているかを示すために使用されるといつも思っていました。

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("DeferredDataId")]
    public virtual DeferredData DeferredData { get; set; }
}

ただし、リンクされた投稿で、これは正しくなく、DeferredData の主キーが Id と呼ばれていたため、実際に必要であることがわかりました。

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }
}

つまりForeignKey、他のクラスを指すために使用されます。

次に、他の参照のいくつかを変更しました。

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }

    public int? SignedOffById { get; set; }
    [ForeignKey("UserId")]
    public virtual UserProfile SignedOffBy { get; set; }
}

しかし、これは失敗しました。これは、クラスForeignKeyの Id を指すために必要であることが判明しました。MemberDataSet

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }

    public int? SignedOffById { get; set; }
    [ForeignKey("SignedOffById")]
    public virtual UserProfile SignedOffBy { get; set; }
}

これは、最初の関係が 1 対 0 または 1 であるのに対し、この 2 番目の関係は 1 対多であり、関係の主要な目的が事実上異なるためだと推測しますが、これについての明確さ/優れた記事への参照をいただければ幸いです。何が起こっているのか、ForeignKey が何をしているのかを正確に理解してください。

public int? DeferredDataId { get; set; }また、上記の例で、明示的にリンクされていない方程式にどのように適合するかを明確にするためにも探していましたDeferredData。これが慣習的に一致することをうれしく思いますが、たとえば、別の名前が付けられている場合、これをどのように明示的に伝えることができますか? 属性の使用についてこの話で見たForeignKeyすべての例ですが、上記のすべてのケースでこれが答えになるわけではありません!

モデルには多くの参照があるため、特定の問題を修正するのではなく、問題を理解することを検討しているため、それぞれにどのようなアプローチを取るかを確立する必要があります。

ありがとう。

編集

役立つ他のクラスを追加しました:

public class DeferredData
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    //other properties
}

public class UserProfile
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }

    //other properties
}
4

3 に答える 3

31

1..0 関係の必要な側には、MemberDataSetへの FK があってはなりませんDeferredData。代わりに、DeferredDataの PK もMemberDataSet(共有主キーと呼ばれる)への FK である必要があります。

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public virtual DeferredData DeferredData { get; set; }
}

public class DeferredData
{
    // DeferredData.Id is both the PK and a FK to MemberDataSet
    [Key]
    [DatabaseGenerated( DatabaseGeneratedOption.None )]
    [ForeignKey( "MemberDataSet" )]
    public int Id { get; set; }

    [Required]
    public virtual MemberDataSet MemberDataSet { get; set; }
}

流暢な API:

modelBuilder.Entity<MemberDataSet>()
    .HasOptional( mds => mds.DeferredData )
    .WithRequired()
    .WillCascadeOnDelete();
于 2014-02-18T14:25:10.063 に答える
0

わずかな例外を除いて、あなたの当初の考えは正しかったと思います。に外部キーをMemberDataSet配置することで、ゼロまたは 1 対多の関係が必要であることを意味します。

あなたの例でMemberDataSet.DeferredDataは、オプションであり、多くのインスタンスDeferredDataで参照できます。MemberDataSet

流暢な構文では、これは次のように表現されます。

modelBuilder.Entity<MemberDataSet>()
    .HasOptional(dataSet => dataSet.DeferredData)
    .WithMany()
    .HasForeignKey(deferredData => deferredData.DeferredDataId);

これを 1 対 0 または 1 のプロパティにするために、MemberDataSet の DeferredDataId 列に一意の (null ではない)キー制約を設定できます。これは、DeferredData エンティティは単一の MemberDataSet エンティティによってのみ参照できることを意味します。

CREATE UNIQUE INDEX unique_MemberDataSet_DeferredDataId ON MemberDataSet(DeferredDataId) WHERE DeferredDataId IS NOT NULL

注:このタイプのフィルター処理されたキーは、SQL Server 2008 以降でのみ使用できます。

于 2015-06-11T01:21:39.133 に答える