c# - 多对多映射表

标签 c# entity-framework ef-code-first many-to-many

根据我在网上和 Programming Entity Framework CodeFirst 一书中看到的示例,当您在两个类上都有一个集合时,EF 会创建一个映射表,例如 MembersRecipes 和每个类的主键将链接到此表。

但是,当我执行以下操作时,我反而在 Recipes 表中获得了一个名为 Member_Id 的新字段,并且在 中获得了一个 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; }
    }

更新: 下面是我尝试过的另一种方法,它不使用 Fluent API 并将 Recipe 上的 AuthorIdAuthor 替换为所有者标志,我还将下面的示例从 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; }

最佳答案

在您的 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 Code First with many to many self referencing relationship

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

这些是从上面的 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)
);

关于c# - 多对多映射表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11382783/

相关文章:

c# - 如何从 C# 应用程序创建 HTML 文本?

c# - 我的 SQLite 数据库是在哪里创建的?

c# - DbContext 丢弃更改而不处理

c# - 如何首先使用 EF 代码在运行时从 ObjectContext 获取实体类型列表?

.net - 使用 Entity Framework 4.0,是否有代码优先数据注释可以为数据库列定义默认值?

c# - 修改实体模型后每个属性为 "Ambiguity between X and X"

c# - 如何将 CssStyleCollection 用于 UserControl?

c# - View 中具有多个(单独的)键的 Entity Framework 关联

c# - EF 代码优先 - IsConcurrencyToken()

c# - WPF 嵌套 ListView ItemsSource