【问题标题】:insert list in db as foreign key value在数据库中插入列表作为外键值
【发布时间】:2016-02-12 15:13:26
【问题描述】:

我有那个数据库

Student 可以有多个 Subject。所以我像这样存储它们:

StudentId:1,姓名:Math; StudentId:1,姓名:地理

等等。

我在 Viewbag 中有主题:

ViewBag.Subjects = new SelectList(new[] { "Math", "Phisic", "Chemic", "English" }
                .Select(x => new { value = x, text = x }),
                "Value", "Text");

并且用户可以一次选择多个项目。 当我注册新学生时,它还必须插入该学生的科目。对他们来说,我就是:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register([Bind(Include = "Id,Name,Surname,BirthDate,Gender,Subject")] Students student)
        {
            if (!ModelState.IsValid)
            {
                SubjectsList();
                return View();
            }
            Student _student = new Student();
            _student.Name = student.Name;
            _student.Surname = student.Surname;
            _student.Gender = student.Gender;
            _student.BirthDate = student.BirthDate;

            Subject _subject = new Subject();
            if (!student.Subject.Any())
            {
                foreach (var item in student.Subject)
                {
                   _db.Subjects.Add(item);//Here it throws an exception Wrong overload
                }
            }


            _db.Students.Add(_student);
            await _db.SaveChangesAsync();

            return RedirectToAction("Index");
        }

我的学生班在这里:

public class Students
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Gender { get; set; }
    public DateTime? BirthDate { get; set; }
    public List<string> Subject { get; set; }
}

我的问题是如何在我的主题表中添加主题值

【问题讨论】:

  • 问题是……
  • 我认为您正在尝试实现类似的目标:stackoverflow.com/questions/33515256/…
  • @venerik 我更新了我的问题
  • 个人认为你的数据模型是错误的;你可以有没有学生的科目,对吧?两个学生共享一个主题呢?实际上,您可能想要的是从主题表中删除 studentId,并创建一个新的“交叉引用”表,其中仅包含 studentIdsubjectId

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


【解决方案1】:

我将暂时避免改进您的数据模型以更好地反映现实的潜力(因为在 cmets 中已经对此进行了一些很好的讨论),所以考虑到什么限制您的实际数据模型如下所示,这是我的答案:

EF(和普通的旧 Linq-To-SQL)的设计方式处理外部 ORM 级别的关键关系,因此您不必这样做。

由 EF 生成的涉及外键的 ORM 实体创建一对多关系作为 List 对象,这些关系称为navigation propertiesThis article 阐明了它的工作原理。

因此,您无需将单个subjects 显式添加到Subject 表中;

由于StudentSubject 表具有外键关系,因此在Student 对象上使用List&lt;Subject&gt; 就足够了,EF 将为您处理插入。


关于您遇到的异常的说明:

您当前的代码有一个学生班级科目的字符串列表:

public List<string> Subject { get; set; }

然后您尝试将字符串插入到 _db.Subjects (DbSet&lt;Subject&gt;) 实例中,这就是您收到异常的原因。


解决方案:

  • 创建一个模拟您的 EF 主题表的 Subjects(因为看起来您正在创建自定义类来模拟 ORM 实体,这是我个人喜欢的一种做法,因为它将 ORM 与最终消费者分离数据,例如您的前端)

  • Students 类更改为具有 List&lt;Subjects&gt; 而不是 List&lt;string&gt; 作为 Subjects 属性。

那么您插入记录的代码大致如下所示:

Student _student = new Student();
_student.Name = student.Name;
_student.Surname = student.Surname;
_student.Gender = student.Gender;          
_student.BirthDate = student.BirthDate;

// I removed the ! here because it seems pointless to check that you have no elements, and then try to add them....
if (student.Subject.Any())
{
    foreach (var item in student.Subjects)
    {
         // this is the ORM subject now, the names seem ambiguous 
         // but the important thing is you have are filling the List<Subject>
         // of the Student ORM entity with Subject ORM entities,
         // which will cause the ORM to handle the foreign key relationship
         // and insert items into the Subjects table

         _student.Subjects.Add(new Subject() { 
             Name = item.Name
         });

         // Note: the ORM will handle the StudentId field, and I assume
         // the Id field is an SQL Identity and will be auto-generated;
         // If not then, aside from, 'why not?', you'd populate it manually
    }
}

那么你仍然只需执行_db.Students.Add(_student); 就可以了。

【讨论】:

    【解决方案2】:

    你的类应该是这样的:

    public class Subject
    {
        public int Id {get;set;}
        public string Name {get;set;}
        public virtual List<Student> Students {get;set;}
    }
    
    public class Student
    {
        public int Id {get;set;}
        public string Name {get;set;}
        public virtual List<Subject> Subjects {get;set;}
    }
    

    然后您可以像这样向学生添加科目:

    var subject = new Subject 
    { 
        Name = "Physics" 
    };
    _db.Subjects.Add(subject);
    
    var student = new Student 
    { 
        Name = "venerik", 
        Subjects = new List<Subject> { subject }
    };
    _db.Students.Add(student);
    _db.SaveChanges();
    

    在此设置中,EF 将为 Student 和 Subject 创建一个表,以及一个名为 SubjectStudent 的交叉表(正如 @Clockwork-Muse 已经建议的那样)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多