我的表格中有一个URL字段用于每个课程。我正在使用它作为路由参数。我这样做是为了让Urls用户友好,根据我的理解,这也可以帮助我在SEO(请纠正我,如果我错了)。有了这样的设置,我无法弄清楚如何创建编辑/删除操作。
Course.cs:课程模型
public partial class Course
{
public int Id { get; set; }
public string Title { get; set; }
// This is set as Unique Key in the table.
public string Url { get; set; }
public string InnerHtml { get; set; }
}
CourseController.cs:控制器和编辑操作,供我们参考。
[HttpPost("Edit/{courseUrl}")]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Administrator")]
public async Task<IActionResult> Edit(string courseUrl, [Bind("Id,Title,Url,InnerHtml")] Course course)
{
var OriginalCourse = await _context.Courses.SingleOrDefaultAsync(m => m.Url == courseUrl);
if (OriginalCourse.Id != course.Id)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(course);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CourseExists(course.Url))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(course);
}
问题:我在此操作中收到以下错误
InvalidOperationException:实体类型的实例&#39; Course&#39;无法跟踪,因为已经跟踪了具有{&#39; Id&#39;}的相同键值的另一个实例。附加现有实体时,请确保仅附加具有给定键值的一个实体实例。考虑使用&#39; DbContextOptionsBuilder.EnableSensitiveDataLogging&#39;查看冲突的键值。
WorkAround:在操作中评论以下代码,让应用程序正常工作。但是,下面的代码是检查正在编辑的模型是否包含在DB中。
var OriginalCourse = await _context.Courses.SingleOrDefaultAsync(m => m.Url == courseUrl);
if (OriginalCourse.Id != course.Id)
{
return NotFound();
}
处理这种情况的正确方法是什么?
答案 0 :(得分:2)
正如错误消息所解释的那样,已经有一个从ORM跟踪的搜索中加载的模型。如果要保存它,则需要将所需的属性复制到跟踪的模型。
//...code removed for brevity
var OriginalCourse = await _context.Courses.SingleOrDefaultAsync(m => m.Url == courseUrl);
if (OriginalCourse.Id != course.Id) {
return NotFound();
}
if (ModelState.IsValid) {
try {
Populate(OriginalCourse, course);
_context.Update(OriginalCourse);
await _context.SaveChangesAsync();
} catch (DbUpdateConcurrencyException) {
if (!CourseExists(course.Url)) {
return NotFound();
} else {
throw;
}
}
return RedirectToAction(nameof(Index));
}
//...code removed for brevity
Populate
看起来像这样
void Populate(Course original, Cource source) {
original.Title = source.Title;
original.Url = source.Url;
original.InnerHtml = source.InnerHtml;
}
另一个选择是不通过不从上下文中选择/返回项目来加载实例
//...code removed for brevity
var exists = await _context.Courses.AnyAsync(m => m.Url == courseUrl);
if (!exists) {
return NotFound();
}
//...code removed for brevity
然后更新提供的课程