【问题标题】:Update Rows in the database with LINQ使用 LINQ 更新数据库中的行
【发布时间】:2020-07-03 06:07:17
【问题描述】:

ASP Core 与 MsSQL

我检查了很多类似问题的答案,但没有找到答案。

Student 表和 Course 表通过联结表 StudentCourse 连接:

Student      StudentCourse       Course
=========    ============        =======
PK | ID      FK | StudentID       PK | ID
   | Name    FK | CourseID           | Name

我想为决定更改课程的学生更新/更改联结 StudentCourse 表中的 CourseId。 我的上下文类:

    public class AppDbContext
    {
        public DbSet<CourseModel> CourseModels { get; set; }
        public DbSet<StudentModel> StudentModels { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<StudentCourse>()
                .HasKey(t => new { t.StudentId, t.CourseId });

            builder.Entity<StudentCourse>()
                .HasOne(sc => sc.Student)
                .WithMany(s => s.StudentCourse)
                .HasForeignKey(sc => sc.StudentId);

            builder.Entity<StudentCourse>()
                .HasOne(sc => sc.Course)
                .WithMany(s => s.StudentCourse)
                .HasForeignKey(sc => sc.CourseId);
        }
    }

我的控制器的方法:

        [HttpPost]
        public IActionResult ChangeCourse(CourseModel newCourse)
        {
            // I want to get course Id for this student
            Guid courseId = (from student in context.StudentModels
                             join cours in context.CourseModels on student.Id equals studentId
                             where cours.Id == oldCourseId
                             select cours.Id).SingleOrDefault();

            // Change course Id
            courseId = newCourse.Id;

            context.SaveChanges();

            return RedirectToAction();
        }

根据Microsoft FAQ ,更新数据库中的一行需要三个步骤:

  1. 在数据库中查询要更新的行。
  2. 对生成的 LINQ to SQL 对象中的成员值进行所需的更改。
  3. 将更改提交到数据库。

所以我按照以下步骤操作:

  1. 在数据库中查询要更新的行。
Guid courseId = (from student in context.StudentModels
                 join cours in context.CourseModels on student.Id equals studentId
                 where cours.Id == oldCourseId
                 select cours.Id).SingleOrDefault();
  1. 对生成的 LINQ to SQL 对象中的成员值进行所需的更改。
oldCourseIdd = newCourse.Id;
  1. 将更改提交到数据库。
context.SaveChanges();

它不会保存更改。我不明白为什么

【问题讨论】:

  • 提交??????????
  • 这是什么:oldCourseIdd?
  • 这里只是迂腐。 LINQ中的Q代表query,没有U代表update。通常我们不使用 LINQ 来更新我们使用它来查询的东西 &lt;/PedanticismOver&gt;
  • “对生成的 LINQ to SQL 对象中的成员值进行所需的更改。”您发布的代码只是这样做。oldCourseIdd 来自哪里?这是“生成的 LINQ to SQL 对象”吗?
  • 这真的是 LINQ to SQL 吗?在我看来更像实体框架; LINQ to SQL 与 EF 完全不同,仅适用于 SQL 服务器,而您已标记 mysql。通过阅读该常见问题解答,我感觉您正在遵循错误的教程;该代码适用于查询,因为 EF 使用 LINQ,但它不是 LtS,所以如果您使用 EF,请不要遵循 LtS 教程

标签: c# mysql linq asp.net-core entity-framework-core


【解决方案1】:

对于你当前的表关系,如果要更新中间表,我的建议是先删除需要更新的数据,再进行添加行的操作。

并且如上面回复所说,不应该使用linq方法更新,而应该基于数据库实体。

试试这些代码来实现:

            var data = context.StudentCourse.Where(x => x.StudentID == studentId  && x.CourseID == oldCourseId).FirstOrDefault();
            context.StudentCourse.Remove(data);
            
           StudentCourse newdata= new StudentCourse()
            {
                StudentID = studentId,
                CourseID = newCourse.Id
            };
            context.StudentCourse.Add(newdata);
            context.SaveChanges();

【讨论】:

  • 感谢您的回答。问题是在我的上下文中没有 DbSet。这就是问题所在。
  • 最后我刚刚添加了 DbSet
【解决方案2】:

您不应该选择基元。 EF 无法追踪。您需要选择StudentCourse 实体。然后您就可以将其设置为CourseID,然后保存更改。

【讨论】:

  • 感谢您的回答。但问题是我的上下文类没有StudentCourse 实体,如上所示。我正在尝试更改联结表中的行而不直接访问它。我可以使用以下命令在 SQL Management Studio 中执行此操作:UPDATE StudentCourse SET CourseId = '9A414E30-DA37-48ED-105E-08D8129A967A' WHERE StudentId = 'A1F38C12-AE65-464C-C489-08D814F4CDDC' 但是如何在 VS 中执行此操作?我试过这段代码:context.StudentModels.FromSqlRaw("UPDATE StudentCourse SET CourseId = {0} WHERE StudentId = {1}", course.Id, studentIdForAll); 但它也不好用。
  • 我知道它不起作用,因为我需要使用 StudentCourse 实体而不是 StudentModels。所以看起来我必须使用StudentCourse 实体来进行更改。但必须有另一种方法。
  • EF 了解当有很多学生和课程实体时:许多如何用中间人表拆分它们,并且学生有课程列表/课程有学生列表..如果你想改变某些学生的课程,从他的列表中删除一门课程并添加另一门课程,然后保存
  • 当然,如果您为 StudentCourse 添加一个 DbSet,那么您可以对其进行操作,但如果没有它,您应该加载例如一个学生的所有课程,然后删除您不想要的课程并添加你做的一个。也许这就是问题所在;您专注于尝试进行更新;专注于删除和插入;这就是你在 c# 对象意义上的做法(你会删除一门课程并添加另一门课程,你不会找到一门课程并尝试将其 id 更改为不同课程的 id)
  • @CaiusJard 谢谢。您的评论很有帮助。
【解决方案3】:

Like Online123321 写道:您需要实体而不是原始实体。 同时更新要求:

context.Entry(entity).State = EntityState.Modified;

更新 不再需要 EntityState.Modified - 对不起,我的错。

如果您的表不在上下文中,也许您可​​以尝试直接执行 SQL?:

context.Database.ExecuteSqlRaw(query)

【讨论】:

  • 真的有必要吗?我认为更改跟踪器检测到它提供的对象的更改,并且只有在(例如)您正在创建一个新对象但希望 EF 将其视为更新对象时才需要这种黑客行为
  • 谢谢。是的,我也看到了这个答案。微软表示没有必要。至少我没有找到相反的说法。
猜你喜欢
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 2015-09-29
相关资源
最近更新 更多