小编典典

多对多映射表

c#

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

但是,当我执行以下操作时,我改为在Recipes表中获得一个新字段,Member_IdRecipe_Id在该Members表中获得a 。

这只会创建两个一对多的关系,而不是一对多的关系,因此我可以将Member 3链接到食谱(4,5,6),将Recipe 4链接到成员(1,2,3)等。

有没有创建此映射表的方法?如果是的话,您如何命名其他名称,例如“ cookbooks”?

谢谢

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

更新: 以下是我尝试过的另一种方法,该方法不使用Fluent
API,并用所有者标志替换AuthorIdAuthorRecipe的内容,我还将以下示例从重命名CookbooksMembersRecipes,这也解决了与答案类似的问题,但如上所述进一步的含义。

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

阅读 292

收藏
2020-05-19

共1个答案

小编典典

在您的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


更新

为了防止对Author属性进行周期性引用,除了上面的内容外,您还需要添加以下内容:

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

想法来源:EF代码优先,具有多对多自引用关系

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

这些是从上面的“代码优先”映射创建的表:

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)
);
2020-05-19