ASP.NET Core Identity自定义数据库结构和完全使用Dapper而非EntityFramework Core
前言
原本本節(jié)內(nèi)容是不存在的,出于有幾個人問到了我:我想使用ASP.NET Core Identity,但是我又不想使用默認生成的數(shù)據(jù)庫表,想自定義一套,我想要使用ASP.NE Core Identity又不想使用EntityFramework Core。真難伺候,哈哈,不過我認為這個問題提出的非常有價值,所以就私下花了點時間看下官網(wǎng)資料,最終經(jīng)過嘗試還是搞出來了,不知道是否滿足問過我這個問題的幾位童鞋,廢話少說,我們直接進入主題吧。
ASP.NET Core Identity自定義數(shù)據(jù)庫表結(jié)構(gòu)
別著急哈,我是那種從頭講到尾的人,博文基本上面向大眾,沒什么基礎(chǔ)的和有經(jīng)驗的都能看明白,也不要嫌棄我啰嗦,好,我說完了,開始,開始,又說了一大堆。大部分情況下對于默認情況下我們都是繼承自默認的身份有關(guān)的類,如下:
/// <summary>/// /// </summary>public class CusomIdentityDbContext : IdentityDbContext<CustomIdentityUser, CustomIdentityRole, string>{/// <summary>/// /// </summary>/// <param name="options"></param>public CusomIdentityDbContext(DbContextOptions<CusomIdentityDbContext> options): base(options){ }}/// <summary>/// /// </summary>public class CustomIdentityUser : IdentityUser { }/// <summary>/// /// </summary>public class CustomIdentityRole : IdentityRole { }然后添加身份中間件,最后開始遷移,如下:
services.AddIdentity<CustomIdentityUser, IdentityRole>().AddEntityFrameworkStores<CusomIdentityDbContext>().AddDefaultTokenProviders();services.AddDbContextPool<CusomIdentityDbContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("Default")));以上是默認為我們生成的數(shù)據(jù)表,我們可以指定用戶表主鍵、可以修改表名、列名等等,以及在此基礎(chǔ)上擴展屬性都是可以的,但是我們就是不想使用這一套,需要自定義一套表來管理用戶身份信息,那么我們該如何做呢?其實呢,官網(wǎng)給了提示,
如下鏈接:https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-custom-storage-providers?view=aspnetcore-2.2,只是說的不是很明確,然后有些童鞋就不知所措了,就是那么幾個Store,自定義實現(xiàn)就好了,來,我們走一個。我們首先自定義用戶,比如如下:
/// <summary>/// /// </summary>public class User{/// <summary>/// /// </summary>public string Id { get; set; }/// <summary>/// /// </summary>public string UserName { get; set; }/// <summary>/// /// </summary>public string Password { get; set; }/// <summary>/// /// </summary>public string Phone { get; set; }}我們再來定義上下文,如下:
/// <summary>/// /// </summary>public class CustomDbContext : DbContext{/// <summary>/// /// </summary>/// <param name="options"></param>public CustomDbContext(DbContextOptions<CustomDbContext> options) : base(options){}/// <summary>/// /// </summary>public DbSet<User> Users { get; set; }}接下來實現(xiàn)IUserStore以及UserPasswordStore接口,接口太多,就全部折疊了
/// <summary>/// /// </summary>public class CustomUserStore : IUserStore<User>, IUserPasswordStore<User>{private readonly CustomDbContext context;/// <summary>/// /// </summary>/// <param name="context"></param>public CustomUserStore(CustomDbContext context){this.context = context;}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> CreateAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> DeleteAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}/// <summary>/// /// </summary>/// <param name="disposing"></param>protected virtual void Dispose(bool disposing){if (disposing){context?.Dispose();}}/// <summary>/// /// </summary>/// <param name="userId"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<User> FindByIdAsync(string userId, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="normalizedUserName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<User> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetNormalizedUserNameAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetPasswordHashAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetUserIdAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetUserNameAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<bool> HasPasswordAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="normalizedName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetNormalizedUserNameAsync(User user, string normalizedName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="passwordHash"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetPasswordHashAsync(User user, string passwordHash, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="userName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetUserNameAsync(User user, string userName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="user"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> UpdateAsync(User user, CancellationToken cancellationToken){throw new NotImplementedException();}} View Code我們還要用到用戶角色表,自定義用戶角色
/// <summary>/// /// </summary>public class CustomUserRole{/// <summary>/// /// </summary>public string Id { get; set; }/// <summary>/// /// </summary>public string UserId { get; set; }/// <summary>/// /// </summary>public string RoleId { get; set; }}接下來再來實現(xiàn)用戶角色Store,如下:
/// <summary>/// /// </summary>public class CustomUserRoleStore : IRoleStore<CustomUserRole>{/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> CreateAsync(CustomUserRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> DeleteAsync(CustomUserRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>public void Dispose(){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="roleId"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<CustomUserRole> FindByIdAsync(string roleId, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="normalizedRoleName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<CustomUserRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetNormalizedRoleNameAsync(CustomUserRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetRoleIdAsync(CustomUserRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetRoleNameAsync(CustomUserRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="normalizedName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetNormalizedRoleNameAsync(CustomUserRole role, string normalizedName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="roleName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetRoleNameAsync(CustomUserRole role, string roleName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> UpdateAsync(CustomUserRole role, CancellationToken cancellationToken){throw new NotImplementedException();}}簡單來說就是根據(jù)需要,看看要不要實現(xiàn)如下幾個Store罷了
- IUserRoleStore
- IUserClaimStore
- IUserPasswordStore
- IUserSecurityStampStore
- IUserEmailStore
- IPhoneNumberStore
- IQueryableUserStore
- IUserLoginStore
- IUserTwoFactorStore
- IUserLockoutStore
然后對于根據(jù)選擇自定義實現(xiàn)的Store都進行注冊,然后進行遷移,如下:
services.AddIdentity<CustomUser, CustomUserRole>().AddDefaultTokenProviders();services.AddDbContextPool<CustomDbContext>(options =>options.UseSqlServer(Configuration.GetConnectionString("Default")));services.AddTransient<IUserStore<CustomUser>, CustomUserStore>();?
沒什么難題,還是那句話,自定義實現(xiàn)一套,不過是實現(xiàn)內(nèi)置的Store,其他通過定義的上下文正常去管理用戶即可。然后什么登陸、注冊之類只需要將對應(yīng)比如UserManager泛型參數(shù)替換成對應(yīng)比如如上CustomUser即可,這個就不用多講了。接下來我們再來看第二個問題,如何不使用EntityFramework而是完全使用Dapper。
完全使用Dapper而不使用EntityFramework Core
其實講解完上述第一個問題,這個就迎刃而解了,我們已經(jīng)完全實現(xiàn)了自定義一套表,第一個問題操作表是通過上下文,我們只需將上下文更換為Dapper即可,如上我們定義了用戶角色表,那我們通過Dapper實現(xiàn)角色表,如下定義角色:
/// <summary>/// /// </summary>public class CustomRole{/// <summary>/// /// </summary>public string Id { get; set; }/// <summary>/// /// </summary>public string Name { get; set; }} /// <summary>/// /// </summary>public class CustomRoleStore : IRoleStore<CustomRole>{private readonly IConfiguration configuration;private readonly string connectionString;/// <summary>/// /// </summary>/// <param name="configuration"></param>public CustomRoleStore(IConfiguration configuration){this.configuration = configuration;connectionString = configuration.GetConnectionString("Default");}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public async Task<IdentityResult> CreateAsync(CustomRole role, CancellationToken cancellationToken){cancellationToken.ThrowIfCancellationRequested();using (var connection = new SqlConnection(connectionString)){await connection.OpenAsync(cancellationToken);role.Id = await connection.QuerySingleAsync<string>($@"INSERT INTO [CustomRole] ([Id],[Name])VALUES (@{Guid.NewGuid().ToString()} @{nameof(CustomRole.Name)});SELECT CAST(SCOPE_IDENTITY() as varchar(36))", role);}return IdentityResult.Success;}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> DeleteAsync(CustomRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>public void Dispose(){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="roleId"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<CustomRole> FindByIdAsync(string roleId, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="normalizedRoleName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<CustomRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetNormalizedRoleNameAsync(CustomRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetRoleIdAsync(CustomRole role, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<string> GetRoleNameAsync(CustomRole role, CancellationToken cancellationToken){return Task.FromResult(role.Name);}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="normalizedName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetNormalizedRoleNameAsync(CustomRole role, string normalizedName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="roleName"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task SetRoleNameAsync(CustomRole role, string roleName, CancellationToken cancellationToken){throw new NotImplementedException();}/// <summary>/// /// </summary>/// <param name="role"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task<IdentityResult> UpdateAsync(CustomRole role, CancellationToken cancellationToken){throw new NotImplementedException();}}別忘記每自定義實現(xiàn)一個Store,然后進行對應(yīng)注冊
services.AddTransient<IRoleStore<CustomRole>, CustomRoleStore>();總結(jié)
這里已經(jīng)提供了完全自定義實現(xiàn)一套表和不使用EntityFramework Core完全使用Dapper的思路,重申一句官網(wǎng)給出了幾個Store,只是未明確說明而已,稍微思考并動手驗證,其實問題不大。
轉(zhuǎn)載于:https://www.cnblogs.com/CreateMyself/p/11291623.html
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core Identity自定义数据库结构和完全使用Dapper而非EntityFramework Core的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决Visual Studio 找不到报
- 下一篇: c 语言 文本处理范例