Home > Enterprise >  Seeding a many:many relationship when the objects to be given to it are being created in the seed da
Seeding a many:many relationship when the objects to be given to it are being created in the seed da

Time:01-10

I'm trying to seed my DB in my DbContext and I don't have any problem but it's more of a logic problem here, I have my seed data as such:

modelBuilder.Entity<Example>().HasData(new Example
            {
                ExampleId = // guid,
                Name = "",
            });

and I'm trying to add one of those entities being created to another one in the seed data, as a many:many relationship. The thing is the only way I've learned to add to a many to many is with the new keyword but that creates a new object, not one that exists already:

modelBuilder.Entity<OtherExample>().HasData(new OtherExample
                {
                    OtherExampleId = // guid,
                    Name = "",
                    Example = new Example
                    {
                        // ...
                    }
                });

But in this case I'd like to add the Example created in the seed data to be added to the OtherExample's Example field.

The way I found to do it was to create the seed, then run a method:

OtherExample.Example.Add(// previously created Example);
context.SaveChanges();

But that's not what I'm looking for. It might work but I want to know if there's a way to directly add it without the new keyword, like when we add to a 1:1 by referencing their Id, but in a many:many.

I'm trying to learn to do this without a Linking Table. I know I could do it in many other ways but I'm really trying to do the following:

modelBuilder.Entity<OtherExample>().HasData(new OtherExample
                    {
                        OtherExampleId = // guid,
                        Name = "",
                        Example = ExampleCreatedBySeed
                    });

// or even this
modelBuilder.Entity<OtherExample>().HasData(new OtherExample
                    {
                        OtherExampleId = // guid,
                        Name = "",
                        Example = new List<Example>()
                        {
                            ExampleCreatedBySeed1,
                            ExampleCreatedBySeed2
                        }
                    });

Even though I imagine that this could create a DB exception due to the fact that the entity might not be created in time for it to be added depending on which order the DB creates the entities but I'm still curious to see if there's a way.

CodePudding user response:

You're talking about a many to many relationships, so why don't you make your seed in the many to many table.

saying these are your models:

public class Author 
{
  public string Id { get; set; }
  public List<AuthorBook> Books { get; set; } = new();
}

public class Book 
{
  public string Id { get; set; }
  public List<AuthorBook> Authors { get;set; } = new();
}

public class AuthorBook 
{
  public string AuthorId { get; set; }
  public Author? Author { get; set; }

  public string BookId { get; set; }
  public Book? Book { get; set; }
}

Method 1

If you insist on using HasData, then you should definitly store something about your seeded models so you can add them in your many to many entity, so you can do it like this:

modelBuilder.Entity<AuthorBook>().HasData(new AuthorBook
                    {
                        Author = PreDefinedAuthor,
                        Book = PreDefinedBook
                    }, // by entity reference which is created and stored before assigning.
                    // OR
                    new AuthorBook
                    {
                        AuthorId = IdOfSeededUser,
                        BookId = IdOfSeededBook
                    }, // by entity id, which is also known and stored before seeding.
    );

Method 2

Create your own seed function which takes the data context and do it manually at startup:

public static class DataSeedHelper
{
  public static void SeedAuthorBooks(DataContext context)
  {
    if (context.AuthorsBooks.Any())
      return;

    var book = new Book() {/*...*/};
    var author = new Author() {/*...*/};
    context.Add(book);
    context.Add(author);
    
    author.Books.Add(new(){Book = book});

    context.SaveChanges();
  }
}
  • Related