Home > OS >  Entity Framework : one entity with multiple many to many relationship
Entity Framework : one entity with multiple many to many relationship

Time:09-15

I'm doing a "manga website" with ASP.NET Core and Entity Framework and Razor pages. What I'm trying to do is having my MangaModul become MangaAuthorArtistGroupScanlationChapterPost Module to speak with multiple many to many modules in the database,for when i want to retrieve information.

An example would be of :

  • a one entity many to many would be Manga Module / Author Module = MangaAuthor Module

  • My Goal is to have a Joint table of all the ICollections MangaAuthorArtistGroupScanlationChapterPost

I am fully aware that I have not made a

protected override void OnModelCreating(ModelBuilder modelBuilder)

I tried using EF6s relationship builder, To fix aMangaAuthorArtist~Modul in the database, however it did not work.

My first guess is that the complexity of relationship isn't doable with automatic EF with these many relationship binding, and I need to write them myself.

2nd guess is that somewhere I'm doing a big mistake in the module where I construct them.

I have read

and several others, but my findings are often same as it's a single many to many relationship (which I already know how to solve)

public class AuthorModel
{
    [Key]
    public int AuthorId { get; set; }

    ~Info~

    ICollection<MangaModel> Models { get; set; }
}

public class ArtistModel
{
    [Key]
    public int ArtistId { get; set; }
    ~Info ~
    ICollection<MangaModel> Models { get; set; }
}

 public class PostModel
 {
    [Key]
    public int PostId { get; set; }

    public int MangaId { get; set; }
    public MangaModel mangaModel { get; set; }
}

public class StudioModel
{
    [Key]
    public int StudioId { get; set; }
    Info
}

public class PostModel
{
    [Key]
    public int PostId { get; set; }
    Info
    public int MangaId { get; set; }
    public MangaModel mangaModel { get; set; }
}

public enum GenresModel
{
     None,
     Action,
     Adult,
     Adventure, 
}

public enum ThemeModel
{       
    None,
    Action,
    Adult,
    Adventure,
}

public class ChapterModel
{
    [Key]
    public int chapterID { get; set; }

    public int MangaId { get; set; }
    public MangaModel mangaModel { get; set; }
}

public class MangaModel
{
    [Key]
    public int MangaID { get; set; }

    [Required(ErrorMessage = "Name is required"),
    MinLength(2, ErrorMessage = "Name must contain at least 2 characters")]
    public string MangaName { get; set; }
         ~Info~
    public GenresModel? Genres { get; set; }
    public ThemeModel? Theme { get; set; }
    ICollection<StudioModel> StudioModels { get; set; }
    ICollection<ArtistModel> ArtistModels { get; set; }
    ICollection<AuthorModel> AuthorModels { get; set; }
    ICollection<ChapterModel> ChaptersModels { get; set; }
    ICollection<PostModel> Posts { get; set; }
    ICollection<GroupScanlatingModel> GroupScanlatingModels { get; set; }
}

public class MangaNNovelAuthDBContext : IdentityDbContext
{
    public MangaNNovelAuthDBContext(DbContextOptions<MangaNNovelAuthDBContext> options) :  base(options)
    {
    }

    public DbSet<ArtistModel> artistModels { get; set; }
    public DbSet<AuthorModel> authorModels { get; set; }
    public DbSet<ChapterModel> chapterModels { get; set; }

    public DbSet<GroupScanlatingModel> groupScanlatingModels { get; set; }

    public DbSet<StudioModel> studioModels { get; set; }
    public DbSet<PostModel> Posts { get; set; }
    public DbSet<MangaModel> mangaModels { get; set; }
}

A photo of the migrated database:

"Edited Wrong picture from another DB, but same problem. Correct picture is now in place." [![A Photo of the database](https://i.stack.imgur.com/2ZxhO.png)]

I have tried creating my own relationship paths with OnModelCreating(ModelBuilder modelBuilder), but it does not give any result.

I have succeeded with a previous work, but the modules were only 2. so It was a single Many to many relationship and not Multiple many to many relationship where several modules speak with the same module

Book and Author, where EF successfully created BookAuthor.

CodePudding user response:

My goal or wish was to have Entity framework build the relationship without fluent API. I am not sure if this will be a "great solve" but i believe this might be a solution to the problem. haven't seen yet what it might devolve into.

I'm still new with EF6, if anyone can give me a better solution or a tip on how to make it easier to control or fewer risk of having larger problems at larger databases.

but Here's the solution
I created a another Module called Master Module; See code below. A photo of a Migrated and Updated database

         protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

             modelBuilder.Entity<MasterModel>()
            .HasKey(m => new
            {
                m.MangaModelId,
                m.GroupsSanlatingId,
                m.postModelID,
                m.ChapterModelId,
                m.ArtistModelID,
                m.AuthorModelID,
                m.StudioModelID
            });

             modelBuilder.Entity<MasterModel>()
            .HasOne(mm => mm.mangaModel)
            .WithMany(m => m.MasterModels)
            .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);
        modelBuilder.Entity<MasterModel>()
            .HasOne(mm => mm.ArtistModel)
            .WithMany(m => m.MasterModels)
            .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);
        modelBuilder.Entity<MasterModel>()
           .HasOne(mm => mm.GroupScanlatingModel)
           .WithMany(m => m.MasterModels)
           .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);

            modelBuilder.Entity<MasterModel>()
           .HasOne(mm => mm.StudioModel)
           .WithMany(m => m.MasterModels)
           .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);

        modelBuilder.Entity<MasterModel>()
           .HasOne(mm => mm.chapterModel)
           .WithMany(m => m.MasterModels)
           .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);

        modelBuilder.Entity<MasterModel>()
           .HasOne(mm => mm.PostModel)
           .WithMany(m => m.MasterModels)
           .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);

        modelBuilder.Entity<MasterModel>()
           .HasOne(mm => mm.AuthorModel)
           .WithMany(m => m.MasterModels)
           .HasForeignKey(mm => mm.MangaModelId).OnDelete(DeleteBehavior.ClientCascade);

        modelBuilder.Entity<ChapterModel>()
            .HasOne(cm => cm.GroupScanlatingModel)
            .WithMany(c => c.chapterModels)
            .HasForeignKey(pt => pt.chapterID).OnDelete(DeleteBehavior.ClientCascade); ;
        base.OnModelCreating(modelBuilder);

         }
          public class MasterModel
{
    [Key]
    public int MasterID { get; set; }
    [Key]
    public int postModelID { get; set; }
    public PostModel PostModel { get; set; }

    [Key]
    public int StudioModelID { get; set; }
    public StudioModel StudioModel { get; set; }
    [Key]
    public int GroupsSanlatingId { get; set; }
    public GroupScanlatingModel GroupScanlatingModel { get; set; }
    [Key]
    public int ChapterModelId { get; set; }
    public ChapterModel chapterModel { get; set; }
    [Key]
    public int AuthorModelID { get; set; }
    public AuthorModel AuthorModel { get; set; }
    [Key]
    public int ArtistModelID { get; set; }
    public ArtistModel ArtistModel { get; set; }
    [Key]
    public int MangaModelId { get; set; }
    public MangaModel mangaModel { get; set; }
}

CodePudding user response:

Saving previous statement if someone might think it's better than this. Previous answer overflows the database and creates a lot of copies. See picture Old Database photo link If the MasterModel get's an input from ChapterModel, ex chapter 2, it creates a new colum, with previous statement. A manga can have hundreds of chapters. If i understand right. The way it's set right now, it will make copies for every previous colum, if there's 4 unique artist. there will be atleast 4x amount of chapters. (unsure if this is true)

But from my understanding this will become messy and fast.

This new Answer i'm doing creates a more normal looking many to many, where the database will get "messy" however, the colums of MasterModel with author will only update on the specific location instead of all Columns that touches artist/author/group etc.
Note: I'm calling blog in the flowchart for Forum. I created a flowchart for how i built my Classes. Hopefully this will make it easier on how i was thinking FlowChart

New Database Photo

     public class MangaNNovelAuthDBContext : IdentityDbContext
      {
        public MangaNNovelAuthDBContext(DbContextOptions<MangaNNovelAuthDBContext> options) : base(options)
    {

    }
    public DbSet<ArtistModel> artistModels { get; set; }
    public DbSet<AuthorModel> authorModels { get; set; }
    public DbSet<ChapterModel> chapterModels { get; set; }

    public DbSet<GroupScanlatingModel> groupScanlatingModels { get; set; }
    public DbSet<UserModel>UserModels { get; set;  }
    public DbSet<StudioModel> studioModels { get; set; }
    public DbSet<PostModel> PostModels { get; set; }
    public DbSet<BlogModel> blogModels { get; set; }
    public DbSet<MangaModel> mangaModels { get; set; }
    public DbSet<MasterModel> MasterModels { get; set; }
     protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
        modelBuilder.Entity<MasterModel>()
       .HasOne(mm => mm.MangaModels)
       .WithOne(i => i.MasterModels)
       .HasForeignKey<MangaModel>(b => b.MangaID);
        base.OnModelCreating(modelBuilder);
        }
    }
    public class ArtistModel : UserModel
      {
          No navigation needed usermodel does it for us and AuthorModel is a replica.
       }

           public class StudioModel : GroupScanlatingModel
          {

                 //Info
             }

        public class BlogModel
    {
    [Key]
    public int id { get; set; }
    public string mangaName { get; set; }
    public ICollection<PostModel> postsModel { get; set; }
    public int mangaId { get; set; }
    public MangaModel MangaModel { get; set; }
    }

           public class PostModel
     {
    [Key]
    public int PostId { get; set; }

    public string Title { get; set; }
    public string postComment { set; get; }

    public int BlogId { get; set; }
    public BlogModel BlogModel { get; set; }

    public string UserID { get; set; }
    public virtual UserModel UserModel { get; set; }
        }

           public class ChapterModel
      {
    [Key]
    public int chapterID { get; set; }
       //Info Dump skippped
 

    public int GroupScanlatingID { get; set; }
    public GroupScanlatingModel GroupScanlatingModels { get; set; }   
      }

           public class GenresModel
         {
    [Key]
    public int GenresId { get; set; }
   // Genres and Tag are replicas will skip Tag
    public int MangaID { get; set; }
    public MangaModel mangaModel { get; set; }
          }


            public class GroupScanlatingModel
       {
    [Key]
    public int GroupScanlatingID { get; set; }
    [Required]
    public string GroupName { get; set; }
    public string? website { get; set; }
    public ICollection<ChapterModel> chapterModels { get; set; }
    public ICollection<MasterModel> MasterModels { get; set; }

    public ICollection<UserModel> userModels { get; set; }
 
      }

          public class MangaModel
         {
    [Key]
    public int MangaID { get; set; }

    [Required(ErrorMessage = "Name is requried"),
    MinLength(2, ErrorMessage = "Name must contain at least 2 characters")]

    public string MangaName { get; set; }
         
    public int BlogModelID { get; set; }
    public BlogModel BlogModel { get; set; }

    public int MasterModelID { get; set; }
    public MasterModel MasterModels { get; set; }
    public ICollection<GenresModel> GenresModels { get; set; }
    public ICollection<TagModel> TagsModels { get; set; }

            }
           public class MasterModel
{
    [Key]
    public int MasterID { get; set; }

    public ICollection<GroupScanlatingModel> GroupScanlating { get; set; }
    public ICollection<UserModel> userModels { get; set; }

    [Required]
    public MangaModel MangaModels { get; set; }
                }

          public class UserModel : IdentityUser
        {

    public string Allias { get; set; }
    public string ForumName { get; set; }
    //navigation 
    public ICollection<GroupScanlatingModel> GroupScanlating { get; set; }
    public ICollection<MasterModel> MasterModel { get; set; }
    public ICollection<PostModel> PostModel { get; set; }
          }
  • Related