SQL Server EF核心行版本并发检查未处理DbConcurrency错误

col17t5w  于 2022-11-21  发布在  其他
关注(0)|答案(2)|浏览(231)

我有一个用EF Core和React开发的项目。我想要的是,如果两个不同的用户同时打开屏幕,并在不同的时间更新相同的数据,则能够给予第二个人一个“更新之前”的错误。但是当我像图片中那样应用它时,它不会捕捉任何错误并更新数据库。一个唯一的新行版本也被分配给数据库。
implementation of what I want in the console app
dbcontext
appservice screenshot
entity screenshot
rowversion column
实作时在项目中更新的点。
在模型上创建:

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

实体:

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

我期望给予错误代码:

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);
    }
f8rj6qna

f8rj6qna1#

如果您正在使用ABP框架(并且您使用框架提供的EfCoreRepository基类来实现存储库),则当您的实体实现IHasConcurrencyStamp接口时,将为您处理所有这些问题。请使用此接口而不是RowVersion。
在资源库/DbContext上调用update之前,请确保将并发戳值分配给实体ConcurrencyStamp属性(由调用方提供)。

xzlaal3s

xzlaal3s2#

当我按如下方式编辑问题中指定的userappservice时,rowversion抛出了错误,我的问题解决了,但我不知道用这样的方法而不是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);
        }

期待您的意见,使这个工作方法足够短。

相关问题