【问题标题】:Issue with many to many relationship using code first mvc使用代码优先mvc的多对多关系问题
【发布时间】:2017-12-26 07:47:12
【问题描述】:

我创建了 Class 和 Teacher 两个模型,我想使用具有两个模型的代码优先方法配置多对多关系。 当我将信息添加到班级和教师表中时,值不会使用多对多关系实体框架代码优先方法插入到 TeacherClasses 表中。

下面是模型和控制器的代码。

这是类模型

public class Class
{
    [Key]
    public int ClassId { get; set; }

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

    public virtual ICollection<Teacher> Teachers { get; set; }

}

这是教师模型

public class Teacher
{
 [Key]  
    public int TeacherId { get; set; }

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

    [DataType(DataType.Date)]
    public DateTime JoiningDate { get; set; }
    public decimal Salary { get; set; }
    public string Email { get; set; }


    public virtual ICollection<Class> Classes { get; set; }


    [NotMapped]
    public virtual Class Class { get; set; }
    [NotMapped]
    public virtual ICollection<int> SelectedClassList { get; set; }

}

这是教师控制器

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "TeacherId,TeacherName,JoiningDate,Salary,Email,Classes,Class,SelectedClassList")] Teacher teacher)
    {
        if (ModelState.IsValid)
        {
            db.Teachers.Add(teacher);
            db.SaveChanges();

            teacher.Classes = new Collection<Class>();

            foreach (var classId in teacher.SelectedClassList)
            {
                teacher.Classes.Add(new Class {ClassId = classId });
            }

            return RedirectToAction("Index");
        }
        return View(teacher);
    }

这是数据库表的图像 in database class, teacher and teacherclasses tables shown

database

这是老师的观点

<div class="form-group">
    @Html.Label("Class List", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @*@Html.ListBox("SelectedClassList", ViewData["ClassList"] as MultiSelectList)
        @Html.ValidationMessageFor(model => model.Classes, "", new { @class = "text-danger" })*@
        @Html.ListBoxFor(model => model.SelectedClassList, new MultiSelectList(ViewBag.ClassList, "value", "text"), new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.SelectedClassList, "", new { @class = "text-danger" })

    </div>
</div>

【问题讨论】:

  • 您遇到了什么错误?数据库表的图像没有帮助。尝试更清楚、更具体地说明问题。
  • 我有错误,在控制器创建操作中使用此代码在 TeacherClasses 表中的值为空。
  • 我首先使用多对多关系EF代码的多选列表框
  • 为什么要将教师添加到它的 dbset 并在 填充类导航属性之前调用 SaveChanges?
  • 我该怎么办?你能设置我的代码吗?请

标签: c# asp.net-mvc entity-framework


【解决方案1】:

根据您的描述和您保存数据的方式,您似乎有两种可能的情况:

  1. 插入教师并将他们连接到现有类。
  2. 现有教师与现有班级联系起来。

无论是什么,规则总是:

  • 首先附加现有实体到上下文
  • 然后添加新实体

所以对于第一个场景来说:

foreach (var classId in teacher.SelectedClassList)
{
    var class = new Class { ClassId = classId }; // "stub" entity
    db.Classes.Attach(class);
    teacher.Classes.Add(class); // Assuming that teacher.Classes isn't null
}
db.Teachers.Add(teacher); // <= Add
db.SaveChanges();

还有第二种情况:

db.Teachers.Attach(teacher); // <= Attach
foreach (var classId in teacher.SelectedClassList)
{
    var class = new Class { ClassId = classId }; // "stub" entity
    db.Classes.Attach(class);
    teacher.Classes.Add(class); // Assuming that teacher.Classes isn't null
}
db.SaveChanges();

如您所见,您永远不需要从数据库中提取现有实体。为了创建关联,所有 EF 需要知道的是两端实体的 ID 值,因此使用 stub 实体 是这里的理想方法。

在第一种情况下,如果您在添加老师之前没有附加课程,那么课程也会被标记为Added,并且您将在数据库中插入空的课程记录(如果它们完全通过验证)。

【讨论】:

  • 我猜在最后一段中,第二个场景实际上是指第一个场景。并且在第二种情况下,链接应该在附加teacher之后添加,否则将不会被检测为修改。
  • 谢谢@Ivan,你当然是对的。我已经在 Stack Overflow 文档条目中详细说明了这一切,但是是的,文档已停止使用,所以我可以快速从内存中恢复(这始终是一个大胆的假设 :))。
猜你喜欢
  • 1970-01-01
  • 2013-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多