C# ASP.NET核心嵌入对象和并发异常
我正在使用此项目学习asp.net core: 我想为讲师对象添加并发异常,该对象包含另一个OfficeAssignment对象 我为这两个对象添加了[Timestamp]属性RowVersion。我让它为讲师对象工作,但对OfficeAssignment位置属性的更改未被检测到 下面是用于回发的更新代码C# ASP.NET核心嵌入对象和并发异常,c#,asp.net,asp.net-core,exception,concurrency,C#,Asp.net,Asp.net Core,Exception,Concurrency,我正在使用此项目学习asp.net core: 我想为讲师对象添加并发异常,该对象包含另一个OfficeAssignment对象 我为这两个对象添加了[Timestamp]属性RowVersion。我让它为讲师对象工作,但对OfficeAssignment位置属性的更改未被检测到 下面是用于回发的更新代码 public async Task<IActionResult> OnPostAsync(int id, int[] selectedCourses) {
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();
}
PostAsync上的公共异步任务(int id,int[]selectedCourses)
{
var讲师=等待上下文讲师
.包括(i=>i.officesignment)
.Include(i=>i.courseasignments)。然后Include(ca=>ca.courses)
.FirstOrDefaultAsync(i=>i.Id==Id);
var officeAssignment=等待_context.officeAssignment
.FirstOrDefaultAsync(oa=>oa.InstructorId==讲师.Id);
如果(讲师==null)
{
返回手柄未找到(讲师);
}
_context.Entry(讲师).Property(“RowVersion”).OriginalValue=讲师.RowVersion;
_context.Entry(officeAssignment).Property(“RowVersion”).OriginalValue=讲师.officeAssignment.RowVersion;
如果(等待TryUpdateModelAsync(
教练,
“讲师”,
i=>i.LastName,i=>i.FirstMidName,i=>i.HireDate,i=>i.officesignment)
{
尝试
{
更新教学课程(上下文、所选课程、讲师);
wait_context.SaveChangesAsync();
返回页首(“/索引”);
}
捕获(DbUpdateConcurrencyException ex)
{
foreach(var exceptionEntry中的var exceptionEntry)
{
如果(exceptionEntry.Entity为讲师)
{
var exceptionEntity=(讲师)exceptionEntry.Entity;
var databaseValues=await exceptionEntry.GetDatabaseValuesAsync();
if(databaseValues==null)
{
返回手柄未找到(讲师);
}
var databaseEntity=(讲师)databaseValues.ToObject();
SetErrorMessage(数据库实体除外);
讲师.RowVersion=数据库实体.RowVersion;
ModelState.Remove(“讲师.RowVersion”);
}
else if(exceptionEntry.Entity为OfficeAssignment)
{
var exceptionEntity=(OfficeAssignment)exceptionEntry.Entity;
var databaseValues=exceptionEntry.GetDatabaseValues();
if(databaseValues==null)
{
返回手柄未找到(讲师);
}
var databaseEntity=(OfficeAssignment)databaseValues.ToObject();
SetErrorMessage(数据库实体除外);
讲师.OfficeAssignment.RowVersion=数据库实体.RowVersion;
ModelState.Remove(“讲师.OfficeAssignment.RowVersion”);
}
}
}
}
普及指定课程数据(上下文、讲师);
返回页();
}
RowVersion
是一个跟踪属性,您需要删除officeAssignment的AsNoTracking()
此外,由于已为这两种模型设置了RowVersion
,因此还需要将原始RowVersion
属性值放入实体的OriginalValues集合中
1.在第页添加以下代码:
<input type="hidden" asp-for="Instructor.OfficeAssignment.RowVersion" />
示例演示:
<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.邮政经办人:
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();
}
公共异步任务OnPostAsync(int?id)
{
如果(!ModelState.IsValid)
{
返回页();
}
var讲师=等待上下文讲师
.包括(i=>i.officesignment)
.FirstOrDefaultAsync(i=>i.ID==ID);
//修改代码如下所示
var officeAssignment=等待_context.officeAssignment
.FirstOrDefaultAsync(oa=>oa.InstructorID==讲师.ID);
_context.Entry(讲师).Property(“RowVersion”).OriginalValue=讲师.RowVersion;
_context.Entry(officeAssignment).Property(“RowVersion”).OriginalValue=讲师.officeAssignment.RowVersion;
如果(等待TryUpdateModelAsync(
教练,
“讲师”,
i=>i.FirstMidName,i=>i.LastName,
i=>i.雇佣,i=>i.离职)
{
尝试
{
更新教学课程(上下文、所选课程、讲师);
wait_context.SaveChangesAsync();
返回页首(“/索引”);
}
捕获(DbUpdateConcurrencyException ex)
{
var exceptionEntry=ex.Entries.Single();
if(exceptionEntry.Entity.GetType()==typeof(OfficeAssignment))
{
//OfficeAssignment类型的配置错误
投掷;
}
其他的
{
//为讲师配置错误