使用其他字段编辑 ASP.Net 核心控制器中的操作



我的表格中都有每门课程的URL字段。我将其用作路由参数。我这样做是为了使 Urls 用户友好,根据我的理解,这也可能对我在 SEO 中有所帮助(如果我错了,请纠正我)。通过这样的设置,我无法弄清楚如何创建编辑/删除操作。

课程.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; }
}

课程控制器.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:无法跟踪实体类型为"Course"的实例,因为已跟踪具有相同 {'Id'} 键值的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。考虑使用"DbContextOptionsBuilder.EnableSensitiveDataLogging"来查看冲突的键值。

解决方法:在操作中注释以下代码,使应用程序正常工作。但是,下面的代码是检查正在编辑的模型是否包含在数据库中。

var OriginalCourse = await _context.Courses.SingleOrDefaultAsync(m => m.Url == courseUrl);
if (OriginalCourse.Id != course.Id)
{
return NotFound();
}

处理这种情况的正确方法是什么?

正如错误消息所解释的那样,已经有一个从搜索中加载的模型正在由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

,然后更新提供的课程

最新更新