簡體   English   中英

Can't update IdentityUser - double SQL update

[英]Can't update IdentityUser - double SQL update

I've got an angular website with Mvc's REST Api. I have just updated it from .net core 2.0 to the newest .Net 6, along with EF Core and AspNetCore.Identity.

I have an extended the AspNetCore's IdentityUser. When I try to update it, there are 2 update requests sent (I found that out using the Sql Server Profiler) - one containing the updated column and the another one resetting it back to the original value. It happens only to the IdentityUser, other entities work normally. As a result, I can't update any user.

They can occasionally come in different order so sometimes the update does work (but more often doesn't).

e.g. when I try something like this

        var user = await UserAccountManager.UserManager.FindByIdAsync(id);
        user.Name = model.Name;
        var result = await UserAccountManager.UserManager.UpdateAsync(user);

After this I would see something like this in the profiler: profiler - 2 updates

As you can see, there are 2 subsequent updates which differ by the Name field and the ConcurrencyStamp.

I've tried to just fetch the user directly from the context e.g.:

                var xx = await Context.Users.SingleOrDefaultAsync(m => m.Id == id);
                xx.Name = model.Name;
                var aa = await Context.SaveChangesAsync();

Same thing.

Even wrapping it all in a transaction didn't work - the SQL requests are separated out but after updating the user there is still another SQL query sent that reverts it back.

I'm pasting in the ConfigureServices function (from Startup.cs) if that helps:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().AddNewtonsoftJson(options => {
                                             options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                                             options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                                         });

        services.AddDbContext<OffWorkDbContext>(options =>
                                                    {
                                                        options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"], b => b.MigrationsAssembly("Hicron.OffWorkPlanner.DataAccessComponent"));
                                                    });

        // add identity
        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<OffWorkDbContext>()
            .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>(o => 
                                            {
                                                // User settings
                                                o.User.RequireUniqueEmail = true;
                                                o.Password.RequireDigit = false;
                                                o.Password.RequireNonAlphanumeric = false;
                                                o.Password.RequireUppercase = false;
                                                o.Password.RequireLowercase = false;
                                                //o.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
                                                //o.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
                                                //o.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
                                            });

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
                          {
                              options.TokenValidationParameters = new TokenValidationParameters
                                                                  {
                                                                      ValidateIssuer = true,
                                                                      ValidateAudience = true,
                                                                      ValidateLifetime = true,
                                                                      ValidateIssuerSigningKey = true,
                                                                      ValidIssuer = Configuration["Token:Issuer"],
                                                                      ValidAudience = Configuration["Token:Issuer"],
                                                                      IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Token:Key"]))
                                                                  };
                          });

        services.AddAuthorization(options =>
                                  {
                                      //add authorization policies 
                                      options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                                          .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                                          .RequireAuthenticatedUser().Build());
                                  });

        Mapper.Initialize(cfg =>
                          {
                              cfg.AddProfile<AutoMapperProfile>();
                          });


        // Add cors
        services.AddCors();

        // Add framework services.
        services.AddMvc(options =>
        {
            options.EnableEndpointRouting = false;
        });


        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
                                   {
                                       configuration.RootPath = "ClientApp/dist";
                                   });

        services.Configure<EmailConfig>(Configuration.GetSection("SmtpConfig"));
        services.AddScoped<IEmailNotifications, EmailNotifications>();
        services.AddScoped<IUserAccountManager, UserAccountManager>();
        services.AddScoped<ITeamService, TeamService>();
        services.AddScoped<IUserService, UserService>();
        services.AddScoped<IDayService, DayService>();
        services.AddScoped<IProjectService, ProjectService>();
        services.AddScoped<IUserCalendarItemService, UserCalendarItemService>();
        services.AddScoped<IDepartmentService, DepartmentService>();
        services.AddTransient<IDatabaseInitializer, DatabaseInitializer>();
    }

Please help me figure out what's going on here (and update the user).

好的,事實證明有 2 個並發請求 - 第 2 個是更新角色,即使角色沒有明確更新用戶,它確實在后台更改了並發時間戳,並且出於某種原因它正在這樣做過時的價值觀。

為了解決這個問題,我們只是將這兩個請求放在一起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM