2011-11-22 10 views
10

Uso EF Code First y tengo un problema en la relación nn, supongo que tenemos un cantante que canta en algunos géneros, entonces necesitamos estos modelos: Artist, Genre, y ArtistsGenres, defino Models como los siguientes:¿Cómo funciona la relación modelo n - n en el código EF Las primeras vistas generadas automáticamente funcionan correctamente?

This es mi artista Modelo:

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

Y mi Modelo Género:

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

Y mi clase de contexto:

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); 
     } 
} 

Pero no hay ninguna relación entre Artistas y Géneros cuando MVC genera vistas automáticamente.

Por ejemplo, necesito cambiar géneros de un artista en la vista de edición, en la vista Crear puedo establecer géneros para un artista, o en la vista de índice quiero mostrar géneros para cada artista. Pero no hay ninguna generación para Géneros en relación con Artist cuando MVC genera vistas automáticamente.

Sé que puedo acceder tanto a géneros como a artistas de ambos lados, pero soy interesante en cuanto a que MVC genere automáticamente vistas como queramos: por ejemplo, para cada artista mostrar géneros relacionados.

¿Cómo puedo hacer esto? ¿Mi modelo es correcto? ¿Es esto cierto para cualquier relación (n a n) que necesite ICollection en ambos lados? ¿O es que necesito algunos elementos en primordial de OnModelCreating método en la clase de contexto, por ejemplo, algo como esto:

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

Por favor, ayúdame, no sé la aplicación exacta de la relación Nton.

Respuesta

0

La conexión entre el artista y los géneros es la ArtistsGenre.

Así artista containt: ID, Nombre

Y Género contiene: ID, Título

Y ArtistsGenre contiene: ID Género del artista, ID

12

Usted no tiene cree un Model por separado para la asociación entre los modelos en una relación muchos a muchos. Realmente el ArtistsGenres no es necesario. Por lo tanto, eliminarlo, y sólo tiene que cambiar su modelBuilder a éste:

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

Se utilizará la tabla ArtistsGenres para asignar una relación de muchos a muchos entre Artists mesa y Genres tabla automáticamente.

Nota: Cuando se define el modelo ArtistsGenres, EF no verlo como una relación, porque se le dice que Hey EF, tengo otro modelo llamado ArtistsGenres! ¡Por favor adminístralo por mí!

Sus nuevas entidades y dbcontext serán los siguientes:

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"); 
     }); 

} 

, hágamelo saber si usted tiene alguna pregunta o necesita aclaraciones sobre cualquier parte.

+0

su derecha, pero esta solución simplemente construir una tabla ArtistsGenres de forma automática y todos los de mi acero problemas sin resolver, no hay relación entre el género y artista en cualquier vista. – Saeid

+0

Edito mi pregunta con su respuesta – Saeid

+0

Si quiere decir que 'MVC' generará' View's con la asociación de modelos automáticamente, en la medida en que sé, ¡no puede! y deberías crear tus propias plantillas 'T4'. ¿Te refieres a esto? Si es así, debe cambiar su Q; si no, explique su propósito más. Saludos –

0

El problema es que no carga explícitamente la colección Genres de la clase de artista y no permite que EF intercepte ese acceso de propiedad al no declararlo como virtual.

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

A continuación, cuando se necesita acceder a la artista y los géneros relacionados que necesita para cargar ellos ansiosos

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

Hacer el Genres propiedad virtual permitirá EF para la carga perezosa la colección si no lo hizo con ganas cárgalo.

+0

Creo que tenemos una visión diferente sobre la pregunta, sé que puedo acceder a Géneros o Artistas de ambos lados, pero estoy interesado en MVC generar automáticamente vistas como queramos: por ejemplo, para cada artista Mostrar géneros relacionados – Saeid

1

Yo sugeriría que se vaya con el enfoque más simple de crear otro modelo ArtistGenre y dejar que figura EF la relación en sí mismo. Crea la tabla como a continuación.

public class ArtistGenre 
{ 
    public int Id; 
    public int GenreId; 
    public int ArtistId; 

    public virtual Genre Genre; 
    public virtual Artist Artist; 
} 

Después de eso, tendrá otra tabla agregada a la base de datos por el nombre anterior con dos propiedades de tecla anterior y una clave principal.

Ahora, puede ejecutar las consultas sobre esta tabla. Dicen

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

Ahora, artista Wil contener todos los artista menor de Género con el Id = 1. También puede hacer lo viceversa para Géneros de la misma manera.

espero que ayude !!

Cuestiones relacionadas