首页 > 解决方案 > 在 .Net Core 2.0 + SQLite EFCore 中,并发检查不适用于“删除”

问题描述

  1. 我首先创建了我的 SQLite 数据库,其中包含所有表
    1. 然后,我使用包管理器控制台中的 Scaffold-DbContext 命令生成了 DbContext 和模型类(用于表)
    2. 我使用一列作为时间戳并创建到 SQLite 触发器以在插入和更新操作后对其进行更新。DATETIME 列实际上是在 SQLite 中创建为 TEXT 的,但这不是这里的问题
    3. 在模型类中,我用[ConcurrencyCheck][DatabaseGenerated(DatabaseGeneratedOption.Computed)]属性装饰了相应的属性(对于 DATETIME 列)
    4. 现在,在通过我的 ASP.Net Core RazorPages 测试我的 CRUD 操作时,我打开了一个(浏览器)选项卡用于编辑,另一个用于删除
    5. 我修改编辑页面中的行内容并保存 - 按预期工作
    6. 现在我转到已经打开的删除页面(显示的内容已经过时,因为它在之前的编辑页面中被修改过)并尝试删除它
    7. 记录被成功删除,而我预计会出现并发异常

为什么会这样?我错过了一些重要的东西吗?提前感谢您的任何帮助/建议。顺便说一句,我在 Windows 10 Pro x64 Build 1709(带有最新更新)和 .Net Core 2.1.104 上使用 Visual Studio 2017 Community 15.6.7(最新)

问候, 瓦桑

我的代码中的一些附加信息

我的表模型类:

[Table("Client_Tags")]
public partial class ClientTags
{
    [Key]
    [Column("ID")]
    [Display(Name = "Row ID")]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    [Required]
    [Column("Client_ID", TypeName = "VARCHAR(255)")]
    [Display(Name = "Client ID")]
    public string ClientId { get; set; }

    [Required]
    [Column("Tag_Name", TypeName = "VARCHAR(255)")]
    [Display(Name = "Tag")]
    public string TagName { get; set; }

    [Column("Last_Updated", TypeName = "DATETIME")]
    [Display(Name = "Last Updated Time")]
    [ConcurrencyCheck]
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public string LastUpdated { get; set; }

}

我的 DbContext.OnModelCreating() 方法的片段:

        modelBuilder.Entity<ClientTags>(entity =>
        {
            entity.HasIndex(e => new { e.ClientId, e.TagName })
                .IsUnique();
        });

我的 Delete.cshtml 中的片段:

<form method="post">
    <input type="hidden" asp-for="ClientTag.Id" />
    <input type="hidden" asp-for="ClientTag.LastUpdated" />"
    <input type="submit" value="Delete" class="btn btn-default" /> |
    <a asp-page="./Index">Back to List</a>
</form>

来自我的 Delete.cshtml.cs 的片段:

    public async Task<IActionResult> OnPostAsync(long? id)
    {
        if (id == null)
        {
            return NotFound();
        }
        ErrMsg throwErrMsg = () =>
        {
            ModelState.AddModelError(
                    string.Empty,
                    "Error updating the values.  Try again later"
                );
            return Page();
        };

        ClientTag = await _context.ClientTags.FindAsync(id);
        if (ClientTag == null)
        {
            return throwErrMsg();
        }

        try
        {
            _context.ClientTags.Remove(ClientTag);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException e)
        {
            return throwErrMsg();
        }

        return RedirectToPage("./Index");
    }

-xxx-

标签: c#entity-frameworksqliteasp.net-coreoptimistic-concurrency

解决方案


这个问题在这个 Entity Framework Core问题上被引用。该问题通过一个工作示例标记为已关闭(并且因为没有提供更多反馈)。

您可能还想查看此博客文章以查看完整的实现并与您的进行比较。


推荐阅读