ASP.NNET Core Identity 多數(shù)據(jù)庫支持
前言
ASP.NET Core Identity 是.NET自帶的身份認證系統(tǒng),支持用戶界面 (UI) 登錄功能,并且管理用戶、密碼、配置文件數(shù)據(jù)、角色、聲明、令牌、電子郵件確認等等。
使用Visual Studio創(chuàng)建帶有identity的項目時,使用SqlServer作為缺省的數(shù)據(jù)庫,本文介紹如何改造為多種數(shù)據(jù)庫支持。
正文
首先,使用Visual Studio 2022創(chuàng)建一個新的ASP.NET Core Web項目,名稱為TestIdentity,選擇身份認證類型為個人賬戶:

創(chuàng)建的項目結(jié)構(gòu)如下:

在Data目錄下保存的是身份認證的DbContext,名稱為ApplicationDbContext,還有基于SqlServer的遷移文件。
我們所要做的第一件事情是將SqlServer部分移動到另一個項目中,然后再增加對其它數(shù)據(jù)庫類型的支持。
現(xiàn)在我們在解決方案中創(chuàng)建一個新的類庫項目,名稱為IdentityEF,在這個項目中安裝包Microsoft.AspNetCore.Identity.EntityFrameworkCore。
然后將ApplicationDbContext移動到這個項目中。

然后我們再創(chuàng)建另一個類庫項目,負責(zé)SqlServer數(shù)據(jù)庫的遷移,名稱為IdentityEF.SqlServer,在這個項目中安裝包Microsoft.EntityFrameworkCore.SqlServer和Microsoft.EntityFrameworkCore.Tools,還要增加對IdentityEF的項目引用,然后將TestIdentity中Data目錄下的Migrations子目錄移動到這個項目中:

然后在這個項目中增加新的類DbContextFactory,代碼如下:
using?Microsoft.EntityFrameworkCore;
using?Microsoft.EntityFrameworkCore.Design;
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Threading.Tasks;
using?TestIdentity.Data;
namespace?IdentityEF.SqlServer
{
????public?class?DbContextFactory?:?IDesignTimeDbContextFactory<ApplicationDbContext>
????{
????????public?ApplicationDbContext?CreateDbContext(string[]?args)
????????{
????????????var?optionsBuilder?=?new?DbContextOptionsBuilder();
????????????optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=aspnet-TestIdentity-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true",
??????????????x?=>?x.MigrationsAssembly("IdentityEF.SqlServer"));
????????????return?new?ApplicationDbContext(optionsBuilder.Options);
????????}
????}
}
請注意,上面的數(shù)據(jù)庫名稱與TestIdentity項目中appsettings.json中定義的DefaultConnection是一樣的,這樣生成的數(shù)據(jù)庫在TestIdentity中可以直接使用。
{
??"ConnectionStrings":?{
????"DefaultConnection":?"Server=(localdb)\\mssqllocaldb;Database=aspnet-TestIdentity-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true"
??},
??"Logging":?{
????"LogLevel":?{
??????"Default":?"Information",
??????"Microsoft.AspNetCore":?"Warning"
????}
??},
??"AllowedHosts":?"*"
}
再增加一個依賴注入擴展IdentityEFExtension,方便在Web應(yīng)用中的引用:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestIdentity.Data;
namespace IdentityEF.SqlServer
{
public static class IdentityEFExtension
{
public static IServiceCollection AddIdentityEFSqlServer(this IServiceCollection services, IConfiguration Configuration)
{
services.AddDbContext(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
x => x.MigrationsAssembly("IdentityEF.SqlServer")));
return services;
}
}
} 到這里,改造基本完畢,在Web應(yīng)TestIdentity項目中,增加對這兩個項目的引用,然后改造Program.cs,將原有的部分注釋掉,增加AddIdentityEFSqlServer:
////?Add?services?to?the?container.
//var?connectionString?=?builder.Configuration.GetConnectionString("DefaultConnection");
//builder.Services.AddDbContext(options?=>
//????options.UseSqlServer(connectionString));
//builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddIdentityEFSqlServer(builder.Configuration);
現(xiàn)在,可以在包管理器中,使用Update-Database創(chuàng)建數(shù)據(jù)庫。
首先,將IdentityEF.SqlServer項目設(shè)置為啟動項目,在包管理器中,將缺省項目也設(shè)置為IdentityEF.SqlServer:

然后運行Update-Database,順利的化,數(shù)據(jù)庫就生成了。
將啟動項目改回到TestIdentity,運行項目,我們可以注冊用戶并進行登錄了。
到這里,針對SqlServer的部分已經(jīng)從Web項目中分離,現(xiàn)在,我們增加對其它數(shù)據(jù)庫類型的支持,比如,我們增加Sqlite的支持。
創(chuàng)建一個新的類庫,名稱為IdentityEF.Sqlite,增加程序包Microsoft.EntityFrameworkCore.Sqlite和Microsoft.EntityFrameworkCore.Tools,還要增加對IdentityEF的項目引用,然后增加DbContextFactory:
using?Microsoft.EntityFrameworkCore;
using?Microsoft.EntityFrameworkCore.Design;
using?TestIdentityEF.Data;
namespace?IdentityEF.Sqlite
{
????public?class?DbContextFactory?:?IDesignTimeDbContextFactory<ApplicationDbContext>
????{
????????public?ApplicationDbContext?CreateDbContext(string[]?args)
????????{
????????????var?optionsBuilder?=?new?DbContextOptionsBuilder();
????????????optionsBuilder.UseSqlite("DataSource=mydatabase.db;",
????????????????x?=>?x.MigrationsAssembly("IdentityEF.Sqlite"));
????????????return?new?ApplicationDbContext(optionsBuilder.Options);
????????}
????}
}
還增加依賴注入擴展:
using?Microsoft.EntityFrameworkCore;
using?Microsoft.Extensions.Configuration;
using?Microsoft.Extensions.DependencyInjection;
using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Threading.Tasks;
using?TestIdentity.Data;
namespace?IdentityEF.Sqlite
{
????public?static?class?IdentityEFExtension
????{
????????public?static?IServiceCollection?AddIdentityEFSqlite(this?IServiceCollection?services,?IConfiguration?Configuration)
????????{
????????????services.AddDbContext(options?=>
????????????????options.UseSqlite(Configuration.GetConnectionString("IdentityConnection"),
????????????????x?=>?x.MigrationsAssembly("IdentityEF.Sqlite")));
????????????return?services;
????????}
????}
}
項目的結(jié)構(gòu)如下:

現(xiàn)在,我們需要生成遷移文件和數(shù)據(jù)庫。
將項目IdentityEF.Sqlite設(shè)置為啟動項目,在程序包管理器中,將IdentityEF.Sqlite設(shè)置為缺省項目:

在程序包管理器中運行:
Add-Migration?init
如果一切順利,在項目文件中會增加遷移文件:

然后運行Update-Database,我們會發(fā)現(xiàn),項目中多了db文件:

最后,改造一下Web應(yīng)用,使其支持Sqlite數(shù)據(jù)庫,并且可以通過配置文件進行切換。
在項目中增加對IdentityEF.Sqlite的引用,然后修改Program.cs:
if?(builder.Configuration["DbType"]=="SqlServer")
????builder.Services.AddIdentityEFSqlServer(builder.Configuration);
else
????builder.Services.AddIdentityEFSqlite(builder.Configuration);
在配置文件中使用DbType切換數(shù)據(jù)庫的類型:
{
??"ConnectionStrings":?{
????//"DefaultConnection":?"Server=(localdb)\\mssqllocaldb;Database=aspnet-TestIdentity-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true",
????"DefaultConnection":?"DataSource=D:\\Asp.Net?Core\\TestIdentityEF\\IdentityEF.Sqlite\\mydatabase.db"
??},
??"DbType":?"Sqlite",
??"Logging":?{
????"LogLevel":?{
??????"Default":?"Information",
??????"Microsoft.AspNetCore":?"Warning"
????}
??},
??"AllowedHosts":?"*"
}
完整的項目代碼可以github下載:https://github.com/zhenl/TestIdentityEF 。
