简体   繁体   English

EF Core Rowversion 并发检查不处理 DbConcurrency 错误

[英]EF Core Rowversion Concurrency Check Not Handle DbConcurrency Error

I have a project that I developed with EF Core and react.我有一个使用 EF Core 开发并做出反应的项目。 What I want is to be able to give the second person an "updated before" error if two different users open the screen at the same time and update the same data at different times.我想要的是如果两个不同的用户同时打开屏幕并在不同时间更新相同的数据,则能够给第二个人一个“更新之前”的错误。 But when I apply it as in the pictures, it does not catch any errors and updates the db.但是当我像图片中那样应用它时,它不会捕获任何错误并更新数据库。 A unique new rowversion is also assigned to the db.一个唯一的新行版本也被分配给数据库。

implementation of what I want in the console app在控制台应用程序中实现我想要的

dbcontext数据库上下文

appservice screenshot应用服务截图

entity screenshot实体截图

rowversion column行版本列

The points I updated in my project while implementing.我在实施时在项目中更新的要点。

on modelcreating:关于模型创建:

modelBuilder.Entity<User>().Property(e => e.RowVersion)
    .IsRequired()
    .IsRowVersion()
    .IsConcurrencyToken();

entity:实体:

  public class User : AbpUser<User>
    {
        [Timestamp]
        public byte[] RowVersion { get; set; }
}

the code i expect to give an error:我希望给出错误的代码:

 public override async Task<UserDto> UpdateAsync(UserDto input) {

        CheckUpdatePermission();

        //input.RowVersion = new byte[] { 0, 0, 0, 0, 0, 0, 7, 215 };

        var user = await _userManager.GetUserByIdAsync(input.Id);

        //MapToEntity(input, user);

        //user.UserName = "hh";

        //user.RowVersion = new byte[] { 1, 2, 0, 0, 0, 0, 9, 85};
        user.RowVersion[1] =55;

        try
        {
            CheckErrors(await _userManager.UpdateAsync(user));
        }
        catch (Exception e)
        {
            throw new UserFriendlyException(e.Message);
        }

        if (input.RoleNames != null)
        {
            CheckErrors(await _userManager.SetRolesAsync(user, input.RoleNames));
        }

        return await GetAsync(input);
    }

If you are using ABP framework (and you use the framework supplied EfCoreRepository base class for your repository implementation) this is all handled for you when your entity implements the IHasConcurrencyStamp interface.如果您正在使用 ABP 框架(并且您使用框架提供的 EfCoreRepository 基础 class 用于您的存储库实现),当您的实体实现IHasConcurrencyStamp接口时,这一切都会为您处理。 Use this instead of RowVersion.使用它而不是 RowVersion。

Make sure you are assigning the concurrency stamp value to the entities ConcurrencyStamp property (supplied by the caller) before calling update on the repository/DbContext.在对存储库/DbContext 调用更新之前,请确保将并发戳值分配给实体ConcurrencyStamp属性(由调用者提供)。

When I edited the userappservice I specified in the question as follows, rowversion threw the error and my problem was solved.当我如下编辑我在问题中指定的 userappservice 时,rowversion 抛出错误,我的问题就解决了。 But I don't know if updating with such a method instead of updateasync will cause any problems.但是我不知道用这样的方法而不是 updateasync 更新是否会导致任何问题。

[UnitOfWork(isTransactional:false)]
        public override async Task<UserDto> UpdateAsync(UserDto input)
        {
            CheckUpdatePermission();

            var user = await _userManager.GetUserByIdAsync(input.Id);

            var options = new DbContextOptionsBuilder<DevFrameTemplateDbContext>()
                   .UseSqlServer(new SqlConnection("customsqlconnectıonstring"))
                   .Options;

            using (DevFrameTemplateDbContext db = new
                DevFrameTemplateDbContext(options))
            {
                User p = await db.Users.AsNoTracking().FirstAsync(x => x.Id == input.Id);
                p.UserName = "Guncellendiiiiiiii";
                p.RowVersion = new byte[] { 0, 0, 0, 0, 0, 0, 39, 22 }; // hatalı verinde error. doğru verince kaydediyor.
                db.Users.Update(p);
                await db.SaveChangesAsync();
            }

            MapToEntity(input, user);

            //try
            //{
                //CheckErrors(await _userManager.UpdateAsync(user));
            //}
            //catch (Exception e)
            //{
                //throw new UserFriendlyException(e.Message);
            //}

            if (input.RoleNames != null)
            {
                CheckErrors(await _userManager.SetRolesAsync(user, input.RoleNames));
            }

            return await GetAsync(input);
        }

Looking forward to your comments to make this working method short enough.期待您的意见,使这个工作方法足够短。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 乐观并发:IsConcurrencyToken和RowVersion - Optimistic concurrency: IsConcurrencyToken and RowVersion 使用 EF Core 在 SQL Server 中处理乐观并发 - 更新子级时,如何更新父级? - Handle Optimistic Concurrency in SQL Server with EF Core - when updating child, how to update the parent? EF 核心检查约束 - EF Core Check constraint EF Core 6“正常”更新方法不尊重 RowVersion 预期行为? - EF Core 6 "normal" update method doesn't respect RowVersion expected behavior? 使用带有 SQL 服务器的 EF Core 2.1 进行正确的并发处理 - Correct concurrency handling using EF Core 2.1 with SQL Server 枚举数组反序列化错误,EF Core - Array of enums deserialization error, EF Core 如何使用 EF Core 处理更改 SQL 服务器数据库列类型 - How to handle changing SQL Server database column type with EF Core EF Core SQL 服务器高效处理许多 WHERE CONTAINS 的方法 - EF Core SQL Server Efficient Way To Handle Many WHERE CONTAINS 尽管检查了应用的迁移,EF Core 幂等迁移脚本仍失败 - EF Core idempotent migration script fails despite check on applied migration 哪种 Java 数据类型适合处理 SqlServer 的 rowversion 数据类型? - Which Java datatype is suitable to handle rowversion datatype of SqlServer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM