首页 文章

多对多映射表

提问于
浏览
59

从我在网上和编程实体框架CodeFirst一书中看到的例子中,当你在两个类上都有一个集合时,EF将创建一个映射表,例如 MembersRecipes ,每个类的主键将链接到该表 .

但是,当我执行下面的操作时,我在 Recipes 表中获取了一个名为 Member_Id 的新字段,并在 Members 表中获得了 Recipe_Id .

这只会创建两个一对多关系,但不会创建多对多关系,因此我可以将成员3链接到食谱(4,5,6)和配方4链接到成员(1,2,3)等 .

有没有办法创建这个映射表?如果是这样,你如何命名其他东西,如“烹饪书”?

谢谢

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: 以下是我尝试过的另一种方法,它不使用Fluent API并将 AuthorIdAuthor 替换为 Recipe 与所有者标志,我也将以下示例从 Cookbooks 重命名为 MembersRecipes ,这也修复了我的问题,类似于答案但如上所述还有其他含义 .

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

RecipeMember 类中,我将集合更改为

public virtual IList<MembersRecipes> MembersRecipes { get; set; }

1 回答

  • 95

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

    你可以用其他方式做到这一点,它是相同的,只是同一枚硬币的另一面:

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

    更多例子:

    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

    要防止对作者属性进行周期性引用,除此之外,您需要添加以下内容:

    modelBuilder.Entity<Recipe>()
        .HasRequired(x => x.Author)
        .WithMany()
        .WillCascadeOnDelete(false);
    

    想法来源:EF Code First with many to many self referencing relationship

    核心问题是,您需要告知EF Author属性(它是一个Member实例)没有Recipe集合(用 WithMany() 表示);这样,可以在作者属性上停止循环引用 .

    这些是上面Code First映射中创建的表:

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

相关问题