How Model n--n relationship in EF Code First to automatically generated views work correctly?

前端 未结 4 1465
离开以前
离开以前 2021-01-11 21:20

I use EF Code First and have a problem in n-n relationship, assume we have a singer that sing in some genres, so we need this models: Artist, Genre, and ArtistsGenres, I def

相关标签:
4条回答
  • 2021-01-11 21:43

    The connection between Artist and genres is the ArtistsGenre.

    So artist containt: ID, Name

    And Genre contains: ID, Title

    And ArtistsGenre contains: ID artist, ID genre

    0 讨论(0)
  • 2021-01-11 21:45

    You haven't to create a separate Model for association between to models in a many-to-many relationship. Really the ArtistsGenres is not necessary. So, remove it, and you just have to change your modelBuilder to this one:

    modelBuilder.Entity<Artist>()
        .HasMany(c => c.Genres)
        .WithMany(x => x.Artists)
        .Map(a => {
            a.ToTable("ArtistsGenres");
            a.MapLeftKey("ArtistId");
            a.MapRightKey("GenreId");
        });
    

    It will use the ArtistsGenres table to map a many-to-many relationship between Artists table and Genres table automatically.

    Note: When you define the ArtistsGenres model, EF will not look at it as a relationship, because you tell him that Hey EF, I have another model named ArtistsGenres! Please manage it for me!!!

    Your new entities and dbcontext will be these:

    public class Artist {
        public long Id { get; set; }
        public string Name { get; set; }
        public ICollection<Genre> Genres { get; set; }
    }
    
    public class Genre {
        public long Id { get; set; }
        public string Title { get; set; }
        public ICollection<Artist> Artists { get; set; }
    }
    
    public class MusicDB : DbContex {
    
        public DbSet<Artist> Artists { get; set; }
        public DbSet<Genre> Genres { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Artist>()
            .HasMany(c => c.Genres)
            .WithMany(x => x.Artists)
            .Map(a => {
                a.ToTable("ArtistsGenres");
                a.MapLeftKey("ArtistId");
                a.MapRightKey("GenreId");
            });
    
    }
    

    Let me know if you have any questions or need clarifications on any part.

    0 讨论(0)
  • 2021-01-11 22:01

    The problem is you are not explicitly loadin the Genres collection of the artist class and you do not allow EF to intercept that property access by not declaring it as virtual.

    public class Artist
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Genre> Genres { get; set; }
    }
    

    Then when you need to access artist and the related genres you need to eager load them

    var artist = db.Artists.Include(a => a.Genres)
          .Where(a => a.Name == "Foo").SingleOrDefault()
    

    Making the Genres property virtual will allow EF to lazy load the collection if you didn't eager load it.

    0 讨论(0)
  • 2021-01-11 22:02

    I would suggest you to go with the simpler approach of creating another model ArtistGenre and let EF figure out the relationship on its own. Create the table as below.

    public class ArtistGenre
    {
        public int Id;
        public int GenreId;
        public int ArtistId;
    
        public virtual Genre Genre;
        public virtual Artist Artist;
    }
    

    After that you will have another table added to the database by the above name with two foriegn key properties and one primary key.

    Now, you can run the queries on this table. Say

    var artist = myContext.ArtistGenre.where( g = g.GenreId == 1).ToList();
    

    Now, artist wil hold all the artist under Genre with Id =1. You can do the vice-versa for Genres too in the similar way.

    Hope it helps !!

    0 讨论(0)
提交回复
热议问题