[英]ASP.NET core embedded object and concurrency exceptions
I am studying asp.net core using this project: https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/read-related-data?view=aspnetcore-3.0&tabs=visual-studio#create-instructor-pages我正在使用这个项目学习 asp.net 核心: https : //docs.microsoft.com/en-us/aspnet/core/data/ef-rp/read-related-data?view= aspnetcore-3.0&tabs =visual- studio#create-instructor-pages
I would like to add concurrency exceptions for the Instructor object, the object contains another object OfficeAssignment.我想为 Instructor 对象添加并发异常,该对象包含另一个对象 OfficeAssignment。 https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/complex-data-model?view=aspnetcore-3.0&tabs=visual-studio
https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/complex-data-model?view=aspnetcore-3.0&tabs=visual-studio
I added [Timestamp] property RowVersion for both objects.我为两个对象添加了 [Timestamp] 属性 RowVersion。 I have it working for the InstructorObject but changes to the OfficeAssignment Location property go undetected.
我让它为 InstructorObject 工作,但未检测到对 OfficeAssignment Location 属性的更改。
Below is the update code used for the postback以下是用于回发的更新代码
public async Task<IActionResult> OnPostAsync(int id, int[] selectedCourses)
{
var instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.CourseAssignments).ThenInclude(ca => ca.Course)
.FirstOrDefaultAsync(i => i.Id == id);
var officeAssignment = await _context.OfficeAssignments
.FirstOrDefaultAsync(oa => oa.InstructorId == instructor.Id);
if (instructor == null)
{
return HandleNotFound(instructor);
}
_context.Entry(instructor).Property("RowVersion").OriginalValue = Instructor.RowVersion;
_context.Entry(officeAssignment).Property("RowVersion").OriginalValue = Instructor.OfficeAssignment.RowVersion;
if (await TryUpdateModelAsync<Instructor>(
instructor,
"Instructor",
i => i.LastName, i => i.FirstMidName, i => i.HireDate, i => i.OfficeAssignment))
{
try
{
UpdateInstructorCourses(_context, selectedCourses, instructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var exceptionEntry in ex.Entries)
{
if (exceptionEntry.Entity is Instructor)
{
var exceptionEntity = (Instructor)exceptionEntry.Entity;
var databaseValues = await exceptionEntry.GetDatabaseValuesAsync();
if (databaseValues == null)
{
return HandleNotFound(instructor);
}
var databaseEntity = (Instructor)databaseValues.ToObject();
SetErrorMessage(exceptionEntity, databaseEntity);
Instructor.RowVersion = databaseEntity.RowVersion;
ModelState.Remove("Instructor.RowVersion");
}
else if (exceptionEntry.Entity is OfficeAssignment)
{
var exceptionEntity = (OfficeAssignment)exceptionEntry.Entity;
var databaseValues = exceptionEntry.GetDatabaseValues();
if (databaseValues == null)
{
return HandleNotFound(instructor);
}
var databaseEntity = (OfficeAssignment)databaseValues.ToObject();
SetErrorMessage(exceptionEntity, databaseEntity);
Instructor.OfficeAssignment.RowVersion = databaseEntity.RowVersion;
ModelState.Remove("Instructor.OfficeAssignment.RowVersion");
}
}
}
}
PopulateAssignedCourseData(_context, instructor);
return Page();
}
RowVersion
is a tracking property, you need to remove the AsNoTracking()
for your officeAssignment
. RowVersion
是追随性,你需要删除AsNoTracking()
为您officeAssignment
。
Besides,since you have set RowVersion
for both models that you also need to put that original RowVersion
property value in the OriginalValues collection for the entity.此外,由于您已为两个模型设置了
RowVersion
,因此您还需要将该原始RowVersion
属性值放入实体的 OriginalValues 集合中。
1.Add below code on Page: 1.在页面添加以下代码:
<input type="hidden" asp-for="Instructor.OfficeAssignment.RowVersion" />
Sample demo:示例演示:
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Instructor.ID" />
<input type="hidden" asp-for="Instructor.RowVersion" />
<div class="form-group">
<label asp-for="Instructor.LastName" class="control-label"></label>
<input asp-for="Instructor.LastName" class="form-control" />
<span asp-validation-for="Instructor.LastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.FirstMidName" class="control-label"></label>
<input asp-for="Instructor.FirstMidName" class="form-control" />
<span asp-validation-for="Instructor.FirstMidName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Instructor.HireDate" class="control-label"></label>
<input asp-for="Instructor.HireDate" class="form-control" />
<span asp-validation-for="Instructor.HireDate" class="text-danger"></span>
</div>
<input type="hidden" asp-for="Instructor.OfficeAssignment.InstructorID" />
<input type="hidden" asp-for="Instructor.OfficeAssignment.RowVersion" />
<div class="form-group">
<label asp-for="Instructor.OfficeAssignment.Location" class="control-label"></label>
<input asp-for="Instructor.OfficeAssignment.Location" class="form-control" />
<span asp-validation-for="Instructor.OfficeAssignment.Location" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
2.POST handler: 2.POST 处理程序:
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
return Page();
}
var instructor = await _context.Instructors
.Include(i => i.OfficeAssignment)
.FirstOrDefaultAsync(i => i.ID == id);
//modified code shown below
var officeAssignment = await _context.OfficeAssignments
.FirstOrDefaultAsync(oa => oa.InstructorID == instructor.ID);
_context.Entry(instructor).Property("RowVersion").OriginalValue = Instructor.RowVersion;
_context.Entry(officeAssignment).Property("RowVersion").OriginalValue = Instructor.OfficeAssignment.RowVersion;
if (await TryUpdateModelAsync<Instructor>(
instructor,
"Instructor",
i => i.FirstMidName, i => i.LastName,
i => i.HireDate, i => i.OfficeAssignment))
{
try
{
UpdateInstructorCourses(_context, selectedCourses, instructor);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
if (exceptionEntry.Entity.GetType() == typeof(OfficeAssignment))
{
//configure error for OfficeAssignment type
throw;
}
else
{
//configure error for Instructor type
var exceptionEntity = (Instructor)exceptionEntry.Entity;
var databaseValues = await exceptionEntry.GetDatabaseValuesAsync();
if (databaseValues == null)
{
return HandleNotFound(instructor);
}
var databaseEntity = (Instructor)databaseValues.ToObject();
databaseEntity.OfficeAssignment = officeAssignment;
SetErorMessage(exceptionEntity, databaseEntity);
Instructor.RowVersion = databaseEntity.RowVersion;
ModelState.Remove("Instructor.RowVersion");
}
}
}
PopulateAssignedCourseData(_context, instructor);
return Page();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.