简体   繁体   中英

EF Code First Self-Referencing Composite Key

I'm making a EF code first MVC model to store articles.

Each article can have multiple pages, so I have made the key a composite key of an ID plus a page number.

I also want articles to have sub-articles, so I want articles to self-reference themselves with a foreign key.

As the key is a composite key I'm struggling with the self-referencing. When I scaffold the model and attempt to use the controls I get 'System.StackOverflowException'

public class Article
    {

        [Key, Column(Order = 0)]
        public int ArticleID { get; set; }

        [Key, Column(Order = 1)]
        public int ArticlePageNo { get; set; }

        public string ArticleTitle { get; set; }

        public string ArticleBody { get; set; }

        [ForeignKey("ArticleID, ArticlePageNo")]
        public Article ArticleParent { get; set; }
    }

I do think that you're not using EF properly, in this case. If I understand corectly your code, EF will try to reference the object to itself and, if you're using an eager loading scenario, that will result in a Stackoverflow exception. So you are actually defining a 1 to 1 relationship between the Article and Article, specifying both the primary key and the foreign key as a composite key formed from ArticleID and ArticlePageNo. Not a thing EF can digest. I would suggest you remodel your data: so you have an one to many relationship between article and page, and a one to many relationship between article and article. The code would look somehing like this:

public class Article
{
    // object unique ID
    public int Id { get; set; }
    public string Title { get; set; }

    // parent Id used as foreign key
    public int? ParentArticleId { get; set; }
    // navigational property for parent
    public virtual Article ParentArticle { get; set; }
    // navigational property for children
    public virtual ICollection<Article> Articles { get; set; }
    // navigational property for article pages
    public virtual ICollection<ArticlePage> Pages { get; set; }
}

public class ArticlePage 
{
    // object unique ID
    public int Id { get; set; }
    public string PageBody { get; set; }

    // parent Id used as foreign key
    public int ArticleId { get; set; }
    // navigational property for parent article
    public virtual Article { get; set; }
}

This model achieves what I was attempting to do but following the feedback I may rethink my approach.

public class Article
{

    [Key, Column(Order = 0)]
    public int ArticleID { get; set; }

    [Key, Column(Order = 1)]
    public int ArticlePageNo { get; set; }

    public string ArticleTitle { get; set; }

    public string ArticleBody { get; set; }

    public int? ParentArticleID { get; set; }
    public int? ParentArticlePageNo { get; set; }

    [ForeignKey("ParentArticleID,ParentArticlePageNo")]
    public virtual Article ArticleParent { get; set; }

    public virtual ICollection<Article> Articles { get; set; }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM