Problems with foreign key (add the entity seed to 'Comment' and specify the foreign key values {'DocumentId'}.) EF

Viewed 617

I have data class initializer

public static class ModelBuilderExtention
{
    public static void Seed(this ModelBuilder modelBuilder)
    {
        List<Document> documents = new List<Document>()
        {
            new Document()
            {
                Id = 1,
                Title = "Top Cat! The most effectual ",
                Date = DateTime.Now.AddDays(-7),
                UserId = "1",
                FileLink = "https://sf-applications.s3.amazonaws.com/Bear/wallpapers/05/july-2020-wallpaper_desktop-3840x1600.png",
                ShortDescription = "Top Cat! Who’s intellectual close friends get to " +
                "call him T.C., providing it’s with dignity. " +
                "Top Cat! The indisputable leader of the gang. He’s the" +
                " boss, he’s a pip, he’s the championship. " +
                "He’s the most tip top, Top Cat.",
                Tags = new List<Tag>() {
                new Tag(){ DocumentId = 1, Id = 1, TagName ="Important"},
                new Tag(){ DocumentId = 1, Id = 2, TagName ="Cat"}
                },
                Comments = new List<Comment>() {
                new Comment(){
                Id = 1,
                Date = DateTime.Now.AddDays(-6),
                DocumentId = 1,
                UserId = "1",
                Content = "Ulysses, Ulysses — Soaring through all the" +
                " galaxies. In search of Earth, flying in to the night" +
                ". Ulysses, Ulysses — Fighting evil and tyranny, with " +
                "all his power, and with all of his might. "
                },
                new Comment(){
                Id = 2,
                Date = DateTime.Now.AddDays(-5),
                DocumentId = 1,
                UserId = "1",
                Content = "Ulysses — no-one else can do the things you do" +
                ". Ulysses — like a bolt of thunder from the blue. Ulysses " +
                "— always fighting all the evil forces bringing peace and justice to all."
                } }
            },
            new Document()
            {
                Id = 2,
                Title = "I never spend much time in school but",
                Date = DateTime.Now.AddDays(-5),
                UserId = "1",
                FileLink = "https://cdn.wallpaperhub.app/cloudcache/1/b/5/8/e/f/1b58ef6e3d36a42e01992accf5c52d6eea244353.jpg",
                ShortDescription = "I taught ladies plenty. It’s true I hire my body out for pay," +
                " hey hey. I’ve gotten burned over Cheryl Tiegs, blown up for Raquel Welch." +
                " But when I end up in the hay it’s only hay, hey hey. I might jump an open " +
                "drawbridge, or Tarzan from a vine.",
                Tags = new List<Tag>() {
                new Tag(){ DocumentId = 2, Id = 3, TagName ="Important"},
                new Tag(){ DocumentId = 2, Id = 4, TagName ="Plenty"}
                },
                Comments = new List<Comment>() {
                new Comment(){
                Id = 3,
                Date = DateTime.Now.AddDays(-5),
                DocumentId = 2,
                UserId = "1",
                Content = "Cause I’m the unknown stuntman that makes Eastwood look so fine."
                },
                new Comment(){
                Id = 4,
                Date = DateTime.Now.AddDays(-4),
                DocumentId = 2,
                UserId = "1",
                Content = "One for all and all for one, Muskehounds are always" +
                " ready. One for all and all for one, helping everybody. "
                } }
            },
            new Document()
            {
                Id = 3,
                Title = "One for all and all for one, it’s a pretty story.Sharing everything with fun, that’s the way to be",
                Date = DateTime.Now.AddDays(-4),
                UserId = "1",
                FileLink = "https://i.pinimg.com/originals/f7/ae/e8/f7aee8753832af613b63e51d5f07011a.jpg",
                ShortDescription = "One for all and all for one, Muskehounds are always ready. " +
                "One for all and all for one, helping everybody.",
                Tags = new List<Tag>() {
                new Tag(){ DocumentId = 3, Id = 5, TagName ="Important"},
                new Tag(){ DocumentId = 3, Id = 6, TagName ="Muskehounds"}
                },
                Comments = new List<Comment>() {
                new Comment(){
                Id = 5,
                Date = DateTime.Now.AddDays(-3),
                DocumentId = 3,
                UserId = "1",
                Content = "I never spend much time in school but I taught ladies plenty."
                },
                new Comment(){
                Id = 6,
                Date = DateTime.Now.AddDays(-3),
                DocumentId = 3,
                UserId = "1",
                Content = "It’s true I hire my body out for pay, hey hey."
                } }
            }
        };
        List<AccessRules> accessRules = new List<AccessRules>()
        {
            new AccessRules()
           {
               Id = 1,
               DocumentId = 1,
               DocumentLink = "Link to document",
               IsPublic = true
           },
            new AccessRules()
            {
                Id = 2,
                DocumentId = 2,
                DocumentLink = "Link to document",
                IsPublic = true
            },
            new AccessRules()
             {
                 Id = 3,
                 DocumentId = 3,
                 DocumentLink = "Link to document",
                 IsPublic = true
             }
        };

        foreach (var document in documents)
        {
            document.AccessRulesId = accessRules[document.Id - 1].Id;
        }

        modelBuilder.Entity<AccessRules>().HasData(accessRules);
          
        modelBuilder.Entity<Document>().HasData(documents);
    }
}

and has 2 main entities Document

public class Document : BaseClass
{
    public string Title { get; set; }
    public DateTime Date { get; set; }
    public string ShortDescription { get; set; }
    public string FileLink { get; set; }
    public List<Tag> Tags { get; set; }
    public List<Comment> Comments { get; set; }
    [NotMapped]
    public AccessRules AccessRules { get; set; }
    [ForeignKey("AccessRules")]
    public int AccessRulesId { get; set; }
    public string UserId { get; set; }
}

and AccessRules

public class AccessRules : BaseClass
{
    [NotMapped]
    public Document Document { get; set; }
    [ForeignKey("DocumentId")]
    public int DocumentId { get; set; }
    public string DocumentLink { get; set; }
    public bool IsPublic { get; set; }
}

and I get this error

enter image description here

The seed entity for entity type 'Document' cannot be added because it has the navigation 'Comments' set. To seed relationships, add the entity seed to 'Comment' and specify the foreign key values {'DocumentId'}.

Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values.

How I must to change entities for them to work?

1 Answers

It seems that in order to seed your data with a many to many relationship, you have to use ModelBuilder's fluent API like this (from comment on EntityFramewor.Docs repo):

            modelBuilder.Entity<Post>()
                .HasMany(p => p.Tags)
                .WithMany(t => t.Posts)
                .UsingEntity<Dictionary<string, object>>(
                    "PostTag",
                    r => r.HasOne<Tag>().WithMany().HasForeignKey("TagId"),
                    l => l.HasOne<Post>().WithMany().HasForeignKey("PostId"),
                    je =>
                    {
                        je.HasKey("PostId", "TagId");
                        je.HasData(
                            new { PostId = 1, TagId = "general" },
                            new { PostId = 1, TagId = "informative" },
                            new { PostId = 2, TagId = "classic" },
                            new { PostId = 3, TagId = "opinion" },
                            new { PostId = 4, TagId = "opinion" },
                            new { PostId = 4, TagId = "informative" });
                    });

It's not very intuitive, and hard to write, but it does seem to allow you to seed many:many relationships in your EF databases.

Related