c# - net - Tabla de asignación de muchos a muchos
one to many entity framework (1)
A partir de ejemplos que he visto en línea y en un libro Programming Framework CodeFirst, cuando tiene una colección en ambas clases, EF crearía una tabla de asignación como MembersRecipes
y la clave primaria de cada clase se vincularía a esta tabla.
Sin embargo, cuando hago lo siguiente, en su lugar, obtengo un nuevo campo en la tabla de Recipes
llamado Member_Id
y un Recipe_Id
en la tabla Members
.
Lo cual solo crea dos relaciones de uno a muchos, pero no muchos, por lo que podría tener el miembro 3 vinculado a las recetas (4,5,6) y la receta 4 vinculada a los miembros (1,2,3), etc.
¿Hay alguna manera de crear esta tabla de mapeo? y si es así, ¿cómo se lo nombra algo más como "libros de cocina"?
Gracias
public abstract class Entity {
[Required]
public int Id { get; set; }
}
public class Member : Entity {
[Required]
public string Name { get; set; }
public virtual IList<Recipe> Recipes { get; set; }
}
public class Recipe : Entity {
[Required]
public string Name { get; set; }
[ForeignKey("Author")]
public int AuthorId { get; set; }
public virtual Member Author { get; set; }
....
public virtual IList<Member> Members { get; set; }
}
ACTUALIZACIÓN: A continuación se muestra otro enfoque que he intentado que no utiliza la API AuthorId
y reemplaza AuthorId
& Author
on Recipe
con una bandera de propietario, también he cambiado el nombre del ejemplo de Cookbooks
a MembersRecipes
, esto también soluciona mi problema similar al respuesta, pero como se ha mencionado tiene implicaciones adicionales.
public class MembersRecipes {
[Key, Column(Order = 0)]
[ForeignKey("Recipe")]
public int RecipeId { get; set; }
public virtual Recipe Recipe { get; set; }
[Key, Column(Order = 1)]
[ForeignKey("Member")]
public int MemberId { get; set; }
public virtual Member Member { get; set; }
public bool Owner { get; set; }
}
y en las clases de Recipe
y Member
cambié las colecciones a
public virtual IList<MembersRecipes> MembersRecipes { get; set; }
Haga esto en su DbContext OnModelCreating:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Recipe>()
.HasMany(x => x.Members)
.WithMany(x => x.Recipes)
.Map(x =>
{
x.ToTable("Cookbooks"); // third table is named Cookbooks
x.MapLeftKey("RecipeId");
x.MapRightKey("MemberId");
});
}
Puedes hacerlo al revés también, es lo mismo, solo otro lado de la misma moneda:
modelBuilder.Entity<Member>()
.HasMany(x => x.Recipes)
.WithMany(x => x.Members)
.Map(x =>
{
x.ToTable("Cookbooks"); // third table is named Cookbooks
x.MapLeftKey("MemberId");
x.MapRightKey("RecipeId");
});
Otros ejemplos:
http://www.ienablemuch.com/2011/07/using-checkbox-list-on-aspnet-mvc-with_16.html
http://www.ienablemuch.com/2011/07/nhibernate-equivalent-of-entity.html
ACTUALIZAR
Para evitar referencias cíclicas en su propiedad de autor, aparte de lo anterior, debe agregar esto:
modelBuilder.Entity<Recipe>()
.HasRequired(x => x.Author)
.WithMany()
.WillCascadeOnDelete(false);
Idea originada aquí: EF Code First con muchas relaciones de autoreferencia
La cuestión principal es que debe informar a EF que la propiedad del autor (que es una instancia miembro) no tiene colecciones de WithMany()
denotado por WithMany()
); De esa forma, la referencia cíclica podría detenerse en la propiedad del Autor.
Estas son las tablas creadas a partir de las asignaciones de Code First anteriores:
CREATE TABLE Members(
Id int IDENTITY(1,1) NOT NULL primary key,
Name nvarchar(128) NOT NULL
);
CREATE TABLE Recipes(
Id int IDENTITY(1,1) NOT NULL primary key,
Name nvarchar(128) NOT NULL,
AuthorId int NOT NULL references Members(Id)
);
CREATE TABLE Cookbooks(
RecipeId int NOT NULL,
MemberId int NOT NULL,
constraint pk_Cookbooks primary key(RecipeId,MemberId)
);