簡體   English   中英

將 AddPooledDbContextFactory 與 AspNetCore.Identity 一起使用

[英]Using AddPooledDbContextFactory with AspNetCore.Identity

我有 asp.net 核心 webapi 應用程序,它目前在Startup class 的ConfigureServices方法中使用Microsoft.AspNetCore.Identityservices.AddDbContext ,到目前為止一切正常。

我嘗試使用services.AddPooledDbContextFactory而不是services.AddDbContext來提高性能。 但是,當我嘗試使用AddPooledDbContextFactory時出現錯誤:

System.InvalidOperationException:嘗試激活“Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore 5[hostapp.Models.AppRole,hostapp.Data.DataContext,System.Int32,hostapp.Models.AppUserRole,Microsoft.AspNetCore.Identity.IdentityRoleClaim時無法解析類型“hostapp.Data.DataContext”的服務5[hostapp.Models.AppRole,hostapp.Data.DataContext,System.Int32,hostapp.Models.AppUserRole,Microsoft.AspNetCore.Identity.IdentityRoleClaim 1[System.Int32]]'

看到這個錯誤后,我創建了新的 webapi 項目,它使用AddPooledDbContextFactory而沒有Microsoft.AspNetCore.Identity工作正常。 所以我的問題是:

services.AddPooledDbContextFactoryMicrosoft.AspNetCore.Identity一起使用以避免上述錯誤的正確方法是什么?

ProjectRoot/Startup.cs

using System.Threading.Tasks;
using hostapp.Data;
using hostapp.GraphQL;
using hostapp.Interfaces;
using hostapp.Models;
using hostapp.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace hostapp
{
    public class Startup
    {
        
        // ...
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<ICookieService, CookieService>();
            
            // EARLIER IMPLEMENTATION WHICH WORKS FINE =>
            // services.AddDbContext<DataContext>(options =>
            // {
            //     options.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
            // });

            // CURRENT IMPLEMENTATION WHICH CAUSES AN ERROR
            services.AddPooledDbContextFactory<DataContext>(options =>
            {
                options.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
            });

            services.AddIdentityCore<AppUser>(opt =>
            {
                opt.Password.RequireNonAlphanumeric = false;
            })
            .AddRoles<AppRole>()
            .AddRoleManager<RoleManager<AppRole>>()
            .AddSignInManager<SignInManager<AppUser>>()
            .AddRoleValidator<RoleValidator<AppRole>>()
            .AddEntityFrameworkStores<DataContext>();

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.Cookie.Name = "app-cookie";
                // options.Cookie.Expiration = TimeSpan.FromMinutes(30);
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return Task.CompletedTask;
                };
            });

            services.AddAuthorization(opt =>
            {
                opt.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
            });

            services
                .AddGraphQLServer()
                .AddAuthorization()
                .AddQueryType<Query>();

            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseCors(options => options
                .AllowAnyHeader()
                .AllowAnyMethod()
                .WithOrigins("https://localhost:4200")
                .SetIsOriginAllowed(origin => true)
                .AllowCredentials());

            app.UseCookiePolicy(new CookiePolicyOptions
            {
                MinimumSameSitePolicy = SameSiteMode.Strict,
                // HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always,
                // Secure = CookieSecurePolicy.Always
            });

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapGraphQL();
            });
        }
    }
}

ProjectRoot/Data/DataContext.cs

using hostapp.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace hostapp.Data
{
    public class DataContext : IdentityDbContext<AppUser, AppRole, int,
                               IdentityUserClaim<int>, AppUserRole, IdentityUserLogin<int>,
                               IdentityRoleClaim<int>, IdentityUserToken<int>>
    {
        public DataContext(DbContextOptions<DataContext> options) : base(options)
        {
        }

        public DbSet<AppUserClaim> Claims { get; set; }
        public DbSet<AppUserClaimOffender> Offenders { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);

            builder.Entity<AppUser>()
                .HasMany(ur => ur.AppUserRoles)
                .WithOne(u => u.AppUser)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();

            builder.Entity<AppRole>()
                .HasMany(ur => ur.AppUserRoles)
                .WithOne(u => u.AppRole)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();
        }
    }
}

ProjectRoot/app.csproj

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0"/>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" NoWarn="NU1605"/>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.0" NoWarn="NU1605"/>
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3"/>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0"/>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0"/>
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.0"/>
    <PackageReference Include="HotChocolate.AspNetCore" Version="11.1.0"/>
    <PackageReference Include="HotChocolate.AspNetCore.Authorization" Version="11.1.0"/>
    <PackageReference Include="HotChocolate.Data.EntityFramework" Version="11.1.0"/>
    <PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0"/>
  </ItemGroup>
</Project>

將 services.AddPooledDbContextFactory 與 Microsoft.AspNetCore.Identity 一起使用以避免上述錯誤的正確方法是什么?

在 ConfigureServices 中,嘗試使用 AddScoped() 方法注冊 DBContext 並使用提供者從服務中獲取工廠。 然后,將實例返回給提供者。 像這樣的代碼:

        services.AddPooledDbContextFactory<DataContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            options.EnableSensitiveDataLogging();
        }, poolSize:32);

        services.AddScoped<DataContext>(p => p.GetRequiredService<IDbContextFactory<DataContext>>().CreateDbContext());

暫無
暫無

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

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