多对多映射表 [英] Many-to-many mapping table

查看:132
本文介绍了多对多映射表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从我在网上看到的示例和编程实体框架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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆