[英]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在控制台应用程序中实现我想要的
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.