Entity Framework 7コードを使用した自己参照外部キー - リレーションシップの定義

ef-fluent-api entity-framework-core

質問

私は以下のようにArticleCommentエンティティを持っています:

public class ArticleComment
 {
    public int ArticleCommentId { get; set; }
    public int? ArticleCommentParentId { get; set; }

    //[ForeignKey("ArticleCommentParentId")]
    public virtual ArticleComment Comment { get; set; }
    public DateTime ArticleDateCreated  { get; set; }
    public string ArticleCommentName { get; set; }
    public string ArticleCommentEmail { get; set; }
    public string ArticleCommentWebSite { get; set; }
    public string AricleCommentBody { get; set; }

    //[ForeignKey("UserIDfk")]   
    public virtual ApplicationUser ApplicationUser { get; set; }
    public Guid? UserIDfk { get; set; }

    public int ArticleIDfk { get; set; }
    //[ForeignKey("ArticleIDfk")]   
    public virtual Article Article { get; set; }


}

私は1つのコメントが多くの返事や子供を持つことができるように、私は、このような流暢なAPIを使用して関係を作成しようとしたような方法で外部キーの関係を定義したい:

builder.Entity<ArticleComment>()
            .HasOne(p => p.Comment)
            .WithMany()
            .HasForeignKey(p => p.ArticleCommentParentId)
            .OnDelete(DeleteBehavior.Restrict)
            .IsRequired(false);

私はここここで提案された解決策に従ったが、メッセージに誤りがある。

FOREIGN KEY制約 'FK_ArticleComment_ArticleComment_ArticleCommentParentId'を 'ArticleComment'テーブルに導入すると、サイクルまたは複数のカスケードパスが発生する可能性があります。 NO DELETE NO ACTIONまたはUP UP NO NO ACTIONを指定するか、他のFOREIGN KEY制約を変更してください。制約またはインデックスを作成できませんでした。以前のエラーを参照してください。

まず、私も設定することにより、 OnDelete(DeleteBehavior.Restrict)私はデータのアノテーションを使用しようとしたも、これは離れて行くだろうが、問題は持続し[ForeignKey("ArticleCommentParentId")]あなたがコメントしたコードを見ることができるようArticleCommentしかし、それはうまくいきませんでしたが、私はこれに感謝します。

受け入れられた回答

エンティティを正しくモデル化していません。各コメントには、ArticleComment型の回答セットが必要です。これらの返信のそれぞれは、その親を指すものです (追加されたICollection Repiesプロパティに注意してください)。

  public class ArticleComment
     {
        public ArticleComment()
        {
            Replies = new HashSet<ArticleComment>();
        }

        public int ArticleCommentId { get; set; }
        public int? ParentArticleCommentId { get; set; }
        public virtual ArticleComment ParentArticleComment{ get; set; }
        public virtual ICollection<ArticleComment> Replies { get; set; }

        //The rest of the properties omitted for clarity...
    }

...と流暢なマッピング:

modelBuilder.Entity<ArticleComment>(entity =>
{
    entity
        .HasMany(e => e.Replies )
        .WithOne(e => e.ParentArticleComment) //Each comment from Replies points back to its parent
        .HasForeignKey(e => e.ParentArticleCommentId );
});

上記の設定では、オープンエンドのツリー構造が得られます。

編集:属性を使用するだけでParentArticleCommentプロパティを装飾する必要があります。この場合、EFは慣習によりすべての関係を解決することを考慮に入れてください。

[ForeignKey("ParentArticleCommentId")]
public virtual ArticleComment ParentArticleComment{ get; set; } 

コレクションのプロパティでは、EFはその関係を理解するのに十分なインテリジェントです。


人気のある回答

私はクラスを単純化して(外部キーサポートフィールドを削除する)、それは動作します。
あなたのEFバージョンの問題かもしれません(実際に私はそれをインストールしましたが、実際に私はrc1を使用していると思いますが、私はいくつかの依存関係の問題があるのでわかりません)。
とにかく、このソースは正常に動作します

public class ArticleComment
{
    public int ArticleCommentId { get; set; }

    public virtual ArticleComment Comment { get; set; }
    public DateTime ArticleDateCreated { get; set; }
    public string ArticleCommentName { get; set; }
    public string ArticleCommentEmail { get; set; }
    public string ArticleCommentWebSite { get; set; }
    public string AricleCommentBody { get; set; }
}

class Context : DbContext
{
    public Context(DbContextOptions dbContextOptions) : base(dbContextOptions)
    {}

    public DbSet<ArticleComment> Comments { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ArticleComment>()
            .HasOne(p => p.Comment)
            .WithMany();

    }
}

static class SampleData
{
    public static void Initialize(Context context)
    {
        if (!context.Comments.Any())
        {
            var comment1 = new ArticleComment()
            {
                AricleCommentBody = "Article 1"
            };

            var comment2 = new ArticleComment()
            {
                AricleCommentBody = "Article 2 that referes to 1",
                Comment = comment1
            };

            context.Comments.Add(comment2);
            context.Comments.Add(comment1);

            context.SaveChanges();
        }
    }
}


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ