简体   繁体   English

ASP.NET 核心嵌入对象和并发异常

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM