EF Core更新Courses表时报错:实体类型'List<Course>'未找到
问题描述
更新数据库Courses表字段时触发错误:
The entity type 'List
' was not found. Ensure that the entity type has been added to the model.
需求:根据复选框状态,将选中为讲师著作的课程的Course.AuthorId设为当前讲师Id;选中为编辑者的课程的Course.EditorId设为当前讲师Id,未选中则置空对应字段。
控制器方法
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> EditInstructorCourse(int id, List<EditInstructorCourseViewModel> model) { if (_context.Courses is null) { return NotFound(); } var courses = await _context.Courses.ToListAsync(); try { for (int i = 0; i < model.Count; i++) { if (model[i].IsAuthor = true) { courses[i].AuthorId = id; _context.Update(courses); } else { courses[i].AuthorId = null; } } _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { throw; } return RedirectToAction(nameof(Index)); }
视图模型
public class EditInstructorCourseViewModel { public string CourseId { get; set; } public string CourseName { get; set; } public string CourseAuthor { get; set; } public string CourseEditor { get; set; } public bool IsAuthor { get; set; } public bool IsEditor { get; set; } }
实体类
public class Instructor { public int Id { get; set; } [DisplayName("Instructor")] public string InstructorName { get; set; } [ForeignKey("AuthorId")] [DisplayName("Author Of")] public ICollection<Course> CoursesAuthored { get; set; } = new List<Course>(); [ForeignKey("EditorId")] [DisplayName("Editor Of")] public List<Course> CoursesEdited { get; set; } = new List<Course>(); } public class Course { public int Id { get; set; } [DisplayName("Course")] public string CourseName { get; set; } public int? AuthorId { get; set; } public Instructor? Author { get; set; } public int? EditorId { get; set; } public Instructor? Editor { get; set; } }
Fluent API配置
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Course>() .HasOne(course => course.Editor) .WithMany(editor => editor.CoursesEdited) .HasForeignKey(course => course.EditorId); modelBuilder.Entity<Course>() .HasOne(course => course.Author) .WithMany(editor => editor.CoursesAuthored) .HasForeignKey(course => course.AuthorId); }
视图代码
@model List<OneToManyMany.Models.ViewModels.EditInstructorCourseViewModel> @{ var instructorId = ViewData["InstructorId"]; var instructorName = ViewData["InstructorName"]; } <h2>Edit Courses for <strong> @instructorName</strong></h2> <div class="form-group"> <label asp-for="@instructorName" class="control-label"></label> <input asp-for="@instructorName" class="form-control" /> <span asp-validation-for="@instructorName" class="text-danger"></span> </div> <div> <form asp-action="EditInstructorCourse" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <input type="hidden" asp-for="@instructorId" /> <div class="form-group"> <h5>Author Of</h5> @for (int i = 0; i < Model.Count; i++) { <div class="form-check m-1"> <input type="hidden" asp-for="@Model[i].CourseId" /> <input type="hidden" asp-for="@Model[i].CourseName" /> <input asp-for="@Model[i].IsAuthor" class="form-check-input" /> <label class="form-check-label" asp-for="@Model[i].IsAuthor"> @Model[i].CourseName </label> </div> } </div> <div class="form-group"> <h5>Editor Of</h5> @for (int i = 0; i < Model.Count; i++) { <div class="form-check m-1"> <input type="hidden" asp-for="@Model[i].CourseId" /> <input type="hidden" asp-for="@Model[i].CourseName" /> <input asp-for="@Model[i].IsEditor" class="form-check-input" /> <label class="form-check-label" asp-for="@Model[i].IsEditor"> @Model[i].CourseName </label> </div> } </div> <div class="mt-4"> <a asp-controller="Instructors" asp-action="Index" asp-route-id="@instructorId" class="btn btn-secondary me-2">Cancel</a> <button id="saveBtn" type="submit" class="btn btn-primary">Save</button> </div> </form> <hr /> </div>
解决方案
核心错误修正
- 错误的
Update调用:_context.Update(courses)传入了List<Course>,但Update方法仅接受单个实体。且从数据库查询的courses已被上下文跟踪,修改属性后无需手动调用Update,上下文会自动追踪变更。 - 赋值而非判断:
if (model[i].IsAuthor = true)是赋值操作,应改为if (model[i].IsAuthor)或if (model[i].IsAuthor == true)。 - 异步方法未加await:
_context.SaveChangesAsync()是异步方法,必须添加await关键字,否则操作未完成就会跳转。 - 实体匹配逻辑错误:直接按索引
i匹配model和courses不安全,两者顺序可能不一致,应通过CourseId关联对应课程。 - 视图参数传递错误:
asp-for="@instructorId"无效,因为instructorId是ViewData中的值,不是模型属性,需改为普通hidden input传递讲师Id到控制器的id参数。
修正后的控制器代码
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> EditInstructorCourse(int id, List<EditInstructorCourseViewModel> model) { if (_context.Courses is null) { return NotFound(); } // 用CourseId建立字典,快速匹配课程 var courseDict = await _context.Courses .ToDictionaryAsync(c => c.Id.ToString()); try { foreach (var item in model) { if (courseDict.TryGetValue(item.CourseId, out var course)) { // 处理作者字段 course.AuthorId = item.IsAuthor ? id : null; // 处理编辑者字段 course.EditorId = item.IsEditor ? id : null; } } await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { throw; } return RedirectToAction(nameof(Index)); }
修正后的视图关键部分
将原视图中的讲师Id隐藏输入替换为:
<input type="hidden" name="id" value="@instructorId" />
同时移除无效的讲师名称输入块(视图模型无对应属性,无需修改):
<!-- 移除以下无效代码 --> <div class="form-group"> <label asp-for="@instructorName" class="control-label"></label> <input asp-for="@instructorName" class="form-control" /> <span asp-validation-for="@instructorName" class="text-danger"></span> </div>
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

