多对多映射表 [英] Many-to-many mapping table
问题描述
从我在网上看到的示例和编程实体框架CodeFirst的书中,当您有两个类的集合时,EF将创建一个映射表,如 MembersRecipes
和每个类的主键将链接到此表。
但是,当我执行以下操作时,我会在 Recipes
表$ code> Member_Id 和 Recipe_Id
在成员
table。
哪些只创建两个一对多的关系,但不是一对多的关系,所以我可以把会员3链接到食谱( 4,5)和配方4链接到会员(1,2,3)等。
有没有办法创建这个映射表?如果是这样,你如何命名其他的东西,如cookbooks?
谢谢
public abstract class Entity {
[必需]
public int Id {get;组;
}
public class成员:Entity {
[必需]
public string Name {get;组; }
public virtual IList< Recipe>食谱{get;组;
}
public class配方:Entity {
[必需]
public string Name {get;组; }
[ForeignKey(Author)]
public int AuthorId {get;组; }
public virtual Member作者{get;组; }
....
public virtual IList< Member>会员{get;组;
}
更新:
以下是另一种方法我已经尝试了不使用Fluent API并替换 AuthorId
& 作者
在食谱
中拥有所有者标志,我也将以下示例从 Cookbooks
到 MembersRecipes
,这也解决了我的问题类似于答案,但是如上所述还有其他的影响。
[ForeignKey(Recipe)]
[Key,Column(Order = 0) public int RecipeId {get;组; }
public virtual配方食谱{get;组;
[Key,Column(Order = 1)]
[ForeignKey(Member)]
public int MemberId {get;组; }
public virtual Member Member {get;组; }
public bool Owner {get;组; }
}
和配方
& 会员
课程我将集合更改为
public virtual IList< MembersRecipes> MembersRecipes {get;组;
在DbContext OnModelCreating上执行此操作:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< Recipe>()
.HasMany(x => x.Members)
.WithMany(x => x.Recipes)
.Map(x =>
{
x.ToTable Cookbooks); //第三个表命名为Cookbooks
x.MapLeftKey(RecipeId);
x.MapRightKey(MemberId);
});
}
你可以这样做,相同,只是另一个相同硬币的一边:
modelBuilder.Entity< Member>()
.HasMany(x => x .Recipes)
.WithMany(x => x.Members)
.Map(x =>
{
x.ToTable(Cookbooks); //第三表名为Cookbooks
x.MapLeftKey(MemberId);
x.MapRightKey(RecipeId);
});
其他示例:
http://www.ienablemuch.com/2011/07/using-checkbox-list-on-aspnet-mvc-with_16.html
< a href =http://www.ienablemuch.com/2011/07/nhibernate-equivalent-of-entity.html =nofollow noreferrer> http://www.ienablemuch.com/2011/07/nhibernate -equivalent-of-entity.html
更新
为了防止您的作者财产的周期性引用,除了上述之外,您需要添加以下内容:
code> modelBuilder.Entity< Recipe>()
.HasRequired(x => x.Author)
.WithMany()
.WillCascadeOnDelete(false);
这里提供的想法: EF Code First with many to many self referenceing relationship
核心的是,您需要通知EF,作者属性(它是一个成员实例)没有配方集合(由 WithMany()
表示);这样,可以在作者属性上停止循环引用。
这些是从上面代码第一个映射创建的表:
$ b code $ c CREATE TABLE成员(
id int IDENTITY(1,1)NOT NULL主键,
名称nvarchar(128)NOT NULL
) ;
CREATE TABLE配方(
ID int IDENTITY(1,1)NOT NULL主键,
名称nvarchar(128)NOT NULL,
AuthorId int NOT NULL references成员(Id)
);
CREATE TABLE Cookbooks(
RecipeId int NOT NULL,
MemberId int NOT NULL,
constraint pk_Cookbooks主键(RecipeId,MemberId)
);
From examples that I have seen online and in a Programming Entity Framework CodeFirst book, when you have a collection on both classes EF would create a mapping table such as MembersRecipes
and the primary key from each class would link to this table.
However when I do the below, I instead get a new field in the Recipes
table called Member_Id
and a Recipe_Id
in the Members
table.
Which only creates two one-to-many relationships, but not a many-to-many so I could have Member 3 linked to Recipes (4,5,6) and Recipe 4 linked to Members (1,2,3) etc.
Is there a way to create this mapping table? and if so how do you name it something else such as "cookbooks" ?
Thanks
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; }
}
UPDATE:
Below is another approach I have tried which doesn't use the Fluent API and replaces the AuthorId
& Author
on Recipe
with an owner flag, I have also renamed the below example from Cookbooks
to MembersRecipes
, this also fixes my issue similar to the answer but as mentioned has further implications.
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; }
}
and in Recipe
& Member
classes I changed the collections to
public virtual IList<MembersRecipes> MembersRecipes { get; set; }
Do this on your 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");
});
}
You can do it the other way around too, it's the same, just another side of the same coin:
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");
});
Further examples:
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
UPDATE
To prevent cyclical reference on your Author property, aside from above, you need to add this:
modelBuilder.Entity<Recipe>()
.HasRequired(x => x.Author)
.WithMany()
.WillCascadeOnDelete(false);
Idea sourced here: EF Code First with many to many self referencing relationship
The core thing is, you need to inform EF that the Author property(which is a Member instance) has no Recipe collections(denoted by WithMany()
); that way, cyclical reference could be stopped on Author property.
These are the created tables from the Code First mappings above:
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)
);
这篇关于多对多映射表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!