多对多&一对多(EF) - 代码优先

时间:2017-06-08 13:42:49

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

为学校型系统创建代码优先数据库。

我正在努力的是课程和用户部分。

用户

  • 可以参加很多课程
  • 可以教多门课程

  • 可以有很多用户
  • 只能有一位老师

以下是我的课程和用户的2个模型

public class User
{
  public virtual ICollection<Course> CoursesRunning { get; set; }

  public virtual ICollection<Course> CoursesTaking { get; set; }

  [DataType(DataType.Date)]
  [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
  [Required]
  public DateTime DoB { get; set; }

  [Required]
  public string EmailAddress { get; set; }

  [Required]
  public string FirstName { get; set; }

  [Required]
  public string LastName { get; set; }

  [Required]
  public string Password { get; set; }

  [Key]
  public int UserId { get; set; }

  public User()
  {
    CoursesRunning = new HashSet<Course>();
    CoursesTaking = new HashSet<Course>();
  }
}

public class Course
{
  [Key]
  public int CourseId { get; set; }

  /// <summary>
  /// The name of the course
  /// </summary>
  public string Name { get; set; }

  /// <summary>
  /// The owner of the course
  /// </summary>
  public virtual User User { get; set; }

  /// <summary>
  /// The users on the course
  /// </summary>
  public virtual ICollection<User> Users { get; set; }

  public Course()
  {
    Users = new HashSet<User>();
  }
}

正如您所看到的,我的用户课程中有我的2个馆藏,然后是课程课程中的单个和多个馆藏。

我必须在我的虚拟属性上设置外键属性,但我真的不确定。

尝试搜索过去几个小时,但看不到任何符合此需求的内容。

谢谢

1 个答案:

答案 0 :(得分:3)

您只需要映射定义每个关系的相应导航属性。

如果您更喜欢数据注释,可以使用InverseProperty属性,如

public class User
{
    [InverseProperty(nameof(Course.User))]
    public virtual ICollection<Course> CoursesRunning { get; set; }

    [InverseProperty(nameof(Course.Users))]
    public virtual ICollection<Course> CoursesTaking { get; set; }
}

public class Course
{
    [InverseProperty(nameof(User.CoursesRunning))]
    public virtual User User { get; set; }

    [InverseProperty(nameof(User.CoursesTaking))]
    public virtual ICollection<User> Users { get; set; }
}

或者您可以使用流畅的配置(我的首选):

modelBuilder.Entity<User>()
    .HasMany(e => e.CoursesRunning)
    .WithRequired(e => e.User)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<User>()
    .HasMany(e => e.CoursesTaking)
    .WithMany(e => e.Users);

注意:在上面的示例中,如果我所做的不是您的意思,您可能需要交换RunningTaking映射。

更新:我几乎总是忘记两个实体之间存在多个关系导致着名的多个级联路径错误。因此,您需要关闭级联删除,并且只能使用流畅的API进行,因此数据注释不是一个选项。