Ash*_*Ash 6 c# entity-framework-core .net-core asp.net-core ef-core-2.2
我正在工作中构建一个新的 .Net Core 2.2 网站,并尝试了几种不同的方法,但在设置 CRUD 模型后使用“编辑”功能时收到错误。最初我从数据库优先方法开始,然后在尝试编辑项目时收到 DbUpdateConcurrencyException。我认为我的数据库或表有问题,所以开始了一个新项目,从新项目中的模型和上下文创建数据库。
环境:
几个月前,我建立了另一个具有相同环境的站点,但没有这样做。
创建步骤:
检查网站运行正常
创建模型和上下文
文件集.cs
using System;
using System.ComponentModel.DataAnnotations;
namespace TestSite.Models
{
public class Fileset
{
public long Id { get; set; }
public string Ticket { get; set; }
public string Requester { get; set; }
[Display(Name = "Research Centre")]
public string ResearchCentre { get; set; }
[Display(Name = "Project ID")]
public string ProjectId { get; set; }
[Display(Name = "Title")]
public string ProjectTitle { get; set; }
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "Internal ID")]
public string InternalId { get; set; }
public string Email { get; set; }
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }
[Display(Name = "End Date")]
public DateTime EndDate { get; set; }
[Display(Name = "Quota (GB)")]
public long Quota { get; set; }
[Display(Name = "UNC Path")]
public string StoragePath { get; set; }
[Display(Name = "AD Group")]
public string Adgroup { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
TestSiteContext.cs
using System;
using Microsoft.EntityFrameworkCore;
namespace TestSite.Data
{
public class TestSiteContext : DbContext
{
public TestSiteContext (DbContextOptions<TestSiteContext> options) : base(options)
{
}
public DbSet<Models.Fileset> Fileset { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
更新 Startup.cs 以包含 DB 的连接字符串参考
services.AddDbContext<Data.TestSiteContext>(options => options.UseSqlServer(Configuration.GetConnectionString("TestDB")));
Run Code Online (Sandbox Code Playgroud)
将连接字符串添加到 appsettings.json
"ConnectionStrings": {
"TestDB": "Server=server;Database=database;Integrated Security=SSPI;Connection Timeout=15"
}
Run Code Online (Sandbox Code Playgroud)
脚手架模型
初始迁移
确认数据库具有新表和正确的架构,并且在 dotnet cli 输出中创建时没有报告错误
导航到kestrel 服务器上的https://localhost:5001/Filesets,创建一个新项目并确认它出现在 SQL 数据库中
错误
"ConnectionStrings": {
"TestDB": "Server=server;Database=database;Integrated Security=SSPI;Connection Timeout=15"
}
Run Code Online (Sandbox Code Playgroud)
我对此比较陌生,但是在遵循教程或在 2.2 版上构建我的第一个站点时,这并没有发生。除了上述步骤,我没有执行任何其他步骤。我不应该因为我独自测试的内容而收到并发错误,除非我故意这样做,即打开一个页面进行编辑,编辑第二页上的项目,然后返回尝试编辑第一页。
任何人都可以帮忙吗?我做了什么蠢事吗?主键和行版本值在我的模型中,并在我的 SQL DB 设计中正确显示。
如果您需要更多信息,请告诉我。
更新
根据要求添加了Edit.cshtml.cs的代码。
DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(int commandIndex, int expectedRowsAffected, int rowsAffected)
Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithPropagationAsync(int commandIndex, RelationalDataReader reader, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple<IEnumerable<ModificationCommandBatch>, IRelationalConnection> parameters, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync<TState, TResult>(TState state, Func<DbContext, TState, CancellationToken, Task<TResult>> operation, Func<DbContext, TState, CancellationToken, Task<ExecutionResult<TResult>>> verifySucceeded, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList<InternalEntityEntry> entriesToSave, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken)
TestSite.Pages.Filesets.EditModel.OnPostAsync() in Edit.cshtml.cs
-
}
_context.Attach(Fileset).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync(); // Error line
}
catch (DbUpdateConcurrencyException)
{
if (!FilesetExists(Fileset.Id))
{
return NotFound();
Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory+GenericTaskHandlerMethod.Convert<T>(object taskAsObject)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory+GenericTaskHandlerMethod.Execute(object receiver, object[] arguments)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeHandlerMethodAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeNextPageFilterAsync()
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Run Code Online (Sandbox Code Playgroud)
我还没有修改它,所以应该是默认的,由脚手架过程创建。
更新 2
在 Neil 的回答和下面的评论之后,我更新了我的 OnPostAsync 方法。
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Fileset).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!FilesetExists(Fileset.Id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./Index");
}
Run Code Online (Sandbox Code Playgroud)
结果是:
The record you attempted to edit was modified by another user after you. The edit operation was canceled and the current values in the database have been displayed. If you still want to edit this record, click the Save button again.
我可以毫无问题地创建和删除记录,但 Edit 不断遇到并发问题。即使第二次回发也不起作用。
问题是Edit.cshtml文件中未引用 RowVersion。
<input type="hidden" asp-for="Fileset.RowVersion" />
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2755 次 |
| 最近记录: |