【问题标题】:ASP.NET MVC Many to Many relationship, using "My Own" tableASP.NET MVC 多对多关系,使用“我自己的”表
【发布时间】:2015-04-23 18:37:40
【问题描述】:

我对在实体框架中使用 Code First 方法相当陌生,而且我知道我与下面的实体有多对多关系,EF 将自动创建中间表:

class Post {
  ...
  public virtual ICollection<Category> Categories {get; set;}
  ... 
}

class Category {
   ...
   public virtual ICollection<Post> Posts {get; set;}
   ...
}

但是,如果在中间表中我需要有额外的数据字段,一种可能的方法(我目前喜欢,也许是因为我不知道更好的方法)是定义我自己的新实体,例如:

class Posts_Categories {
   public int Id {get; set;}
   public int CategoryId {get; set;}
   public int PostId {get; set;}
   public string Exrtafield1 {get; set;}
   public int ex extraField2 {get; set;}
   ...
   public virtual Post Post {get; set;}
   public virtual Category Category {get; set;}
}

使用这种方法,EF 确实创建了我的自定义中间表,但它也创建了另一个名为“PostsCategories”的自己的中间表,它只包含一个指向 Post_Id 的外键和另一个指向 Category_Id 的外键。

如何让它不创建额外的一个并使用我定义的那个? 这是管理具有额外数​​据字段的多对多关系的好方法吗?

【问题讨论】:

标签: asp.net-mvc ef-code-first many-to-many entity-framework-6


【解决方案1】:

你应该像这样使用一对多关系:

public class Post
{
    public System.Int32 PostId { get; set; }

    [InverseProperty("Post")]
    public virtual ICollection<Posts_Category> PostCategories { get; set; }
}

public class Category
{
    public System.Int32 CategoryId { get; set; }

    [InverseProperty("Category")]
    public virtual ICollection<Posts_Category> PostCategories { get; set; }
}

public class Posts_Category
{
    public System.Int32 PostId { get; set; }

    public System.Int32 CategoryId { get; set; }

    [ForeignKey("PostId")]
    [InverseProperty("PostCategories")]
    public virtual Post Post { get; set; }

    [ForeignKey("CategoryId")]
    [InverseProperty("PostCategories")]
    public virtual Category Category { get; set; }
}

【讨论】:

  • 哇,@Iraj,我正要发布类似的解决方案,你打败了我,我同意,这是要走的路,这样它不会创建另一个表,你仍然可以访问 Category 中的所有帖子和 Post 中的所有类别。
  • 谢谢@Iraj,我稍后会研究它,因为首先我必须学习你在这里使用的几个新关键字,比如我不知道的 InverseProperty。我可能会再问你一些问题!非常感谢兄弟!
  • @behroozdalvandi:请查看此链接可能对您有所帮助:msdn.microsoft.com/en-us/data/jj591583.aspx
【解决方案2】:

我需要对 Iraj 的回答进行一些扩展以使其发挥作用。另一个修改是我将默认的ApplicationUser 作为我的表之一。

所以关系是ApplicationUser 1-∞ IdeaVote ∞-1 Idea(即有用户和想法,用户可以对想法进行投票,每个投票都由ApplicationUserIdea

public class Idea
{
    [Key]
    public int Id { get; set; }

    // This is an ordinary data field
    public string Text { get; set; }

    [InverseProperty("Idea")]
    public virtual ICollection<IdeaVote> Votes { get; set; }
}

public class IdeaVote
{
    [Key]
    public int Id { get; set; }

    public int IdeaId { get; set; }
    [ForeignKey("IdeaId")]
    [InverseProperty("Votes")]
    public virtual Idea Idea { get; set; }

    public string UserId { get; set; }
    [ForeignKey("UserId")]
    [InverseProperty("Votes")]
    public virtual ApplicationUser User { get; set; }
}
public class ApplicationUser : IdentityUser
{
    [InverseProperty("User")]
    public virtual ICollection<IdeaVote> Votes { get; set; }

    // Default stuff
}

【讨论】:

    【解决方案3】:

    它为两者之间的关系创建 PostsCategories 表是正常的,你会想要的。如果 c 是一个类别,您将能够执行 c.Posts 之类的操作

    通常您不会为此手动创建自己的表。您会在“额外”字段中保留哪些类型的数据?我可能会将这些字段移动到其他表之一并删除该表。大多数多对多关系表不包含额外字段。

    【讨论】:

    • 谢谢克里斯。我知道大多数 m2m 关系没有额外的字段,但有些有。只需考虑一个课程表、一个学生表和一个 StudentCourse 表,这些表记录了哪些学生有哪些课程以及每门课程的成绩。该成绩必须在一个额外的领域。如果您能告诉我如何实现我的想法,我将不胜感激。
    • 这里有一个答案,有 187 个赞成票,我相信这正是您想要做的。这不是最容易完成的事情,但我希望这会有所帮助。 stackoverflow.com/questions/7050404/…
    • 感谢克里斯,提供有用的链接 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多