简体   繁体   English

EF代码中的模型n - n关系如何自动生成视图正常工作?

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

I use EF Code First and have a problem in nn relationship, assume we have a singer that sing in some genres, so we need this models: Artist, Genre, and ArtistsGenres, I define Models as following: 我使用EF Code First并且在nn关系中存在问题,假设我们有一个歌手在某些类型中唱歌,所以我们需要这个模型:Artist,Genre和ArtistsGenres,我将模型定义如下:

This is My Artist Model: 这是我的艺术家模型:

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

And My Genre Model: 和我的类型模型:

public class Genre
{
    public long Id { get; set; }
    public string Title { get; set; }
    public ICollection<Artist> Artists { get; set; }
}

And my context class: 我的上下文类:

public class MusicDB : DbContex
{
    public DbSet<Artist> Artists { get; set; }
    public DbSet<Genre> Genres { get; set; }
    public DbSet<ArtistsGenres> ArtistsGenres { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Entity<Artist>()
            .HasMany(a => a.Genres)
            .WithMany(g => g.Artists)
            .Map(model => {
                model.ToTable("ArtistsGenres");
                model.MapLeftKey("Artist_Id");
                model.MapRightKey("Genre_Id");
            });

        base.OnModelCreating(modelBuilder);
        }
}

But there is not any relationship between Artists and Genres when MVC generate views automatically. 但是当MVC自动生成视图时,Artists和Genres之间没有任何关系。

For example, I need to change Genres of an Artist in edit view, in Create view I can set Genres for an Artist, or in Index View I want show genres for each Artist. 例如,我需要在编辑视图中更改艺术家的类型,在创建视图中我可以为艺术家设置流派,或者在索引视图中我想要为每个艺术家显示流派。 But there isn't any generation for Genres in relation to Artist when MVC generate views automatically. 但是当MVC自动生成视图时,与Artist相关的Genres没有任何代。

I know I can access both Genres and Artists from both side but I am interesting in MVC automatically generate views as we want: for ex: for each artist show related Genres. 我知道我可以从两边访问流派和艺术家,但我很有兴趣MVC自动生成我们想要的视图:例如:每个艺术家节目相关的流派。

How can I do this? 我怎样才能做到这一点? Is my model correct? 我的模特是否正确? Is this true for any (n to n) relation that needs ICollection on both side? 这对于任何需要ICollection的(n到n)关系都是如此吗? Or do I need some elements in overriding of OnModelCreating method in context class, for example something like this: 或者在上下文类中重写OnModelCreating方法时是否需要一些元素,例如:

modelBuilder.Entity<Artist>()
    .HasMany(a => a.Genres)
    .WithMany(g => g.Artists);

Please help me, I don't know the exact implementation of NtoN relationship. 请帮帮我,我不知道NtoN关系的确切实现。

You haven't to create a separate Model for association between to models in a many-to-many relationship. 您不必为多对多关系中的模型之间的关联创建单独的Model Really the ArtistsGenres is not necessary. 真的是ArtistsGenres是没有必要的。 So, remove it, and you just have to change your modelBuilder to this one: 所以,删除它,你只需要将modelBuilder更改为:

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. 它将使用ArtistsGenres表自动映射Artists表和Genres表之间的多对多关系。

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 ! 注意:当您定义ArtistsGenres模型时,EF不会将其视为关系,因为您告诉他Hey EF,我有另一个名为ArtistsGenres模型! Please manage it for me!!! 请为我管理!!!

Your new entities and dbcontext will be these: 您的新实体和dbcontext将是这些:

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. 如果您对任何部分有任何疑问或需要澄清,请与我们联系。

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. 我建议你采用更简单的方法来创建另一个模型ArtistGenre,并让EF自己找出这种关系。 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. 之后,您将通过上述名称将另一个表添加到数据库中,其中包含两个foriegn键属性和一个主键。

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. 现在,艺术家将使用Id = 1将所有艺术家置于Genre之下。 You can do the vice-versa for Genres too in the similar way. 你也可以用类似的方式为Genres做反之亦然。

Hope it helps !! 希望能帮助到你 !!

The connection between Artist and genres is the ArtistsGenre. 艺术家和流派之间的联系是ArtistsGenre。

So artist containt: ID, Name 所以艺术家包含:ID,Name

And Genre contains: ID, Title 并且类型包含:ID,标题

And ArtistsGenre contains: ID artist, ID genre 而ArtistsGenre包含:ID艺术家,ID类型

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 . 问题是您没有显式加载艺术家类的Genres集合,并且您不允许EF通过不将其声明为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. 如果您没有急切加载它,那么将Genres属性设置为虚拟将允许EF延迟加载集合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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