【问题标题】:asp.net core 3.1 EF ConcurrencyCheck not working using razor CRUD scaffolding not MVCasp.net core 3.1 EF ConcurrencyCheck不能使用剃须刀CRUD脚手架而不是MVC
【发布时间】:2020-09-02 16:46:42
【问题描述】:

我是 ConcurrencyCheck 的新手,我开始了一个新的空白 asp.net 核心 VStudio 项目,我只使用 Razor 页面和 CRUD razor 脚手架。当我尝试使用 [ConcurrencyCheck] 设置的模型类属性进行更改时,即使我是唯一一个在调试模式下访问我的测试设置和 dbase 的人,我也会得到 DbUpdateConcurrencyException。我不明白 ConcurrencyCheck 应该如何工作吗?我认为它不应该遇到任何异常。

这是我的代码.. 都是 vanilla/blank VStudio 项目,只是下面的上下文和模型类文件以外的默认内容。

我的背景

 public class AppDbContext :DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options)
         : base(options)
        {
        }

        public DbSet<CustInfo> cust_info { get; set; }
    }

我的模特

public class CustInfo
    {
        [Key]
        public int request_id { get; set; }

        [ConcurrencyCheck]
        public string customer_name { get; set; }

        [ConcurrencyCheck]
        public string customer_phone { get; set; }

        [ConcurrencyCheck]
        public string customer_email { get; set; }
    }

我的编辑剃须刀页面 .cs

public class EditModel : PageModel
    {
        private readonly TestApp.Classes.AppDbContext _context;

        public EditModel(TestApp.Classes.AppDbContext context)
        {
            _context = context;
        }

        [BindProperty]
        public CustInfo CustInfo { get; set; }

        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            CustInfo = await _context.cust_info.FirstOrDefaultAsync(m => m.request_id == id);

            if (CustInfo == null)
            {
                return NotFound();
            }
            return Page();
        }

        // To protect from overposting attacks, enable the specific properties you want to bind to, for
        // more details, see https://aka.ms/RazorPagesCRUD.
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            _context.Attach(CustInfo).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!CustInfoExists(CustInfo.request_id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return RedirectToPage("./Index");
        }

        private bool CustInfoExists(int id)
        {
            return _context.cust_info.Any(e => e.request_id == id);
        }
    }

当我在编辑页面并更改说客户的电子邮件地址时,然后单击保存按钮,如果在“await _context.SaveChangesAsync();”上设置了断点行,它会遇到以下异常

{“数据库操作预计会影响 1 行,但实际上影响了 0 行。自加载实体以来,数据可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=527962。 "}

我希望不会有任何例外,所以无法弄清楚为什么这不起作用。我认为保存到 dbase 会起作用,因为我是唯一一个更改调试这个项目的任何东西的人。如果我从模型类中的 customer_name、customer_phone 和 customer_email 中删除 [ConcurrencyCheck],然后更改其中任何一个,则不会发生异常。只是想弄清楚这些东西,这样我就可以用断点测试调试这个项目,然后从 sql 端更改数据库中的一个值,然后看到一个实际的并发问题发生了:) 但我什至无法让它工作,即使我' m 不会在数据库中更改任何内容。

【问题讨论】:

    标签: c# asp.net asp.net-core


    【解决方案1】:
    1. 当您执行_context.Attach(CustInfo).State = EntityState.Modified; 时,没有关于您的实体在数据库中的实际状态的信息。您必须从数据库中获取您的实体,对其进行更改,然后保存更改。
    2. 我建议您从CustInfo 类中删除所有ConcurrencyCheck 属性,并添加另一个类型为byte[] 的属性,该属性使用TimestampAttribute 进行注释,它将扮演并发令牌的角色。 EF 在插入或更新时自动生成其值,并在更新操作期间检查其值是否被其他人更改,以防止并发访问。

    【讨论】:

    • 我看到了那个方法,所以如果我使用时间戳,那么我不需要 [ConcurrencyCheck] 属性 OK gotcha。
    猜你喜欢
    • 2021-04-19
    • 1970-01-01
    • 2020-07-15
    • 2022-12-29
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 2014-06-13
    • 2020-06-02
    相关资源
    最近更新 更多