Migragtion的命令,左边是手动命令,右边是代码方式html
首先来看命令方式:git
建立一个mvc项目,默认已经集成了EF包github
建立的项目包含了Microsoft.AspNetCore.Identity.EntityFramewordCore包,这将使用Entity Framework Core经过SQL Server来储存身份识别的数据和表信息。sql
添加Sql链接字符串:数据库
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "conn": "Data Source=pc;User ID=sa;Password=12;database=CoreDb;Connect Timeout=30;Encrypt=False;
TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" } }
注意这个:ConnectionStrings 是必需要这样写的,默认是根据这个名字读取,后面会说cookie
Net Core 身份 Identity 容许向应用中添加登录功能。用户可建立一个帐户并进行登录,登录时可以使用用户名、密码mvc
Server数据库存储用户名字、密码和配置文件数据。另外,你可以使用其余已有的存储空间存储数据app
建立ApplicationUser, ApplicationRole 分别继承IdentityRole IdentityUser异步
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; namespace IdentityDemo.Models { public class ApplicationRole:IdentityRole { } }
using Microsoft.AspNetCore.Identity; namespace IdentityDemo.Models { public class ApplicationUser : IdentityUser { } }
建立上下文类:async
using IdentityDemo.Models; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace IdentityDemo.Date { public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } } }
ConfigureServices 中注册服务
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Login"; }); services.AddDbContext<ApplicationDbContext>(options => { //配置文件前面必须是;ConnectionStrings //由于默认是:GetSection("ConnectionStrings")[name]. options.UseSqlServer(Configuration.GetConnectionString("conn")); //options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); }); services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); //配置密码注册方式 services.Configure<IdentityOptions>(options => { options.Password.RequireLowercase = false; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.Password.RequiredLength = 1; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
我这里用了Cookie验证,因此应该添加中间件 app.UseAuthentication();
建立用户:经过依赖注入: UserManager 和 SignInManager 依赖:Microsoft.AspNetCore.Identity;
private readonly UserManager<ApplicationUser> _userManager; private readonly SignInManager<ApplicationUser> _signinManager; public LoginController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signinManager) { _userManager = userManager; _signinManager = signinManager; }
注册代码
[HttpPost] public async Task<IActionResult> Registe(LoginViewModel model) { var identityUser = new ApplicationUser { UserName = model.UserName, PasswordHash = model.PassWorld, NormalizedEmail = model.UserName }; var identityResult = await _userManager.CreateAsync(identityUser, model.PassWorld); if (identityResult.Succeeded) { return RedirectToAction("Index", "Home"); } return View(); }
注册以前,咱们先经过命令生成数据库
命令依赖于:Microsoft.EntityFrameworkCore.Tools包,不过默认也有了
能够输入dotnet ef migrations --help 看看帮助
输入后命令:dotnet ef migrations add identity
项目中会生成一个Migrations的文件夹和文件
而后更新数据库:dotnet ef migrations update
能够看到生成了数据库和表,但AspNetUsers表的组建ID默认是字符串类型的,一连串GUID,待会会说改为经常使用的int类型
好了。如今注册一个看看
看看默认的:
接下来咱们修改默认的主键为int类型。只须要改为:IdentityUser<int> ,IdentityRole<int>
上下文改为:
由于是从新生成数据库,须要删除数据库,而且把Migrations的文件都删除,或者直接删除Migrations文件夹
能够执行命令删除库:dotnet ef database drop
不然EF会看成升级和降级处理,不会从新生成数据库
而后从新migragins add ,update 注册看看,已是int类型了
而后给表升级,在用户表添加一列 TrueName,首先看用户名表。默认是没有该列的
咱们在ApplicationUser类新增字段
而后命令:dotnet ef migrations add AddTrueName //AddTrueName名字是任意取的
此时在Migrations文件夹生成了对呀的类
而后update,这里的update只会找最新的migrations 这里的最新的migrations就是20190126061435_identity
数据库已经有了
好比咱们在添加一个Address列,而后在还原到只有TrueName的状态
如今Migrations有3个Migration
而后咱们经过update回滚
dotnet ef database update 回滚的migration
咱们这里回滚到AddTrueName 那么命令就是:dotnet ef database update AddTrueName
回滚以后。表也更新了
其实__EFMigrationsHistory表是保存了当前全部的Migration
回滚前
回滚后
这里有两个AddTrueName是由于我add了两次,能够不用管
主要是对比以前和以后,AddAddress没有了
而后看:dotnet ef migrations script 生成脚本
生成脚本在屏幕中,还得拷贝出来,多不友好,看看--help,是能够指定路径的
执行: dotnet ef migrations script -o d:\script\user.sql
打开生成的文件看看
dotnet ef migratoins remove 是移除最新的一个migration,remove一次就移除一次,
前提是该migration没有update到database,若是细心你会发现,当你add migration时候,会提示,能够remove 移除
咱们添加3个 migration 分别是 temp01,temp02,temp03
此时已经添加了3个测试的
记住,我这里都没有执行update的,因此在__EFMigrationsHistory也不会记录。该表记录的是已经update到database的migration
咱们执行一次命令:dotnet ef migrations remove
由于temp03是最后添加的,因此先删除,是否是像入栈出栈
在remove一次,按照上面说的,应该是移除temp02
就不一一测试了
来看看,若是update 后。能不能remove,上面已经还原到了TrueName
咱们先升级到Address
执行命令:dotnet ef database update Addaddress
表字段和历史纪录也都有了
而后咱们执行命令:dotnet ef migrations remove
这里要注意一点,咱们是加了Adress后,我为了测试,又加了temp01,02,03,上面测试只remove了03,02
若是你没有remove01的话,如今remove是remove的01,注意下就行了
如今咱们默认01,02,03都已经remove了。最新的确定就是address了
好了,有点啰嗦。执行命令:dotnet ef migrations remove
info提示该migratin已经udate到database
经过dotnet ef migrations remove --help
能够看到有其余选项,有兴趣的能够自行研究
上面都是手动执行命令,咱们来看看在代码里面怎么作
在程序初始化的时候,添加一个默认管理员的帐号,实例代码以下
建立一个ApplicationDbContextSeed类,用于建立默认用户
using IdentityDemo.Models; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace IdentityDemo.Date { public class ApplicationDbContextSeed { private UserManager<ApplicationUser> _userManger; /// <summary> /// /// </summary> /// <param name="context">上下文</param> /// <param name="server">依赖注入的容器,这里能够获取依赖注入</param> /// <returns></returns> public async Task AsyncSpeed(ApplicationDbContext context, IServiceProvider server) { try { _userManger = server.GetRequiredService<UserManager<ApplicationUser>>(); var logger = server.GetRequiredService<ILogger<ApplicationDbContext>>(); logger.LogInformation("speed Init"); //若是没有用户,则建立一个 if (!_userManger.Users.Any()) { var defaultUser = new ApplicationUser { UserName = "Admin", dEmail = "cnblogs@163.com" }; var userResult = await _userManger.CreateAsync(defaultUser, "123456"); if(!userResult.Succeeded) { logger.LogError("建立失败"); //logger.LogInformation("初始化用户失败"); userResult.Errors.ToList().ForEach(e => { logger.LogError(e.Description); }); } } } catch (Exception ex) { throw new Exception("初始化用户失败"); } } } }
添加一个对IWebHost扩展的类:
using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; namespace IdentityDemo.Date { public static class WebHostMigrationExtensions { public static IWebHost MigrationDbContext<TContext>(this IWebHost host, Action<TContext, IServiceProvider> sedder) where TContext : DbContext { using (var scope = host.Services.CreateScope()) { //拿到依赖注入容器 var servers = scope.ServiceProvider; //var logger = servers.GetRequiredService<ILogger<TContext>>(); var logger = servers.GetService<ILogger<TContext>>(); var context = servers.GetService<TContext>(); try { context.Database.Migrate(); sedder(context, servers); logger.LogInformation($"执行DbContex{typeof(TContext).Name}seed方法成功"); } catch (Exception ex) { logger.LogError(ex, $"执行DbContex{typeof(TContext).Name}seed方法失败"); } } return host; } } }
这样就能够在Program.cs的main方法中调用
由于方法是异步方法,因此用Wait()方法改成同步的
而后删除Migration中的全部文件,从新add,能够 不update,由于代码会:context.Database.Migrate();
而后数据库已经初始化了
经过var user = _userManager.FindByEmailAsync("cnblogs@163.com").Result;能够查找用户,
[HttpPost] public IActionResult Login(LoginViewModel model) { var user = _userManager.FindByEmailAsync(model.Email).Result; if (user!=null) { var claims = new List<Claim> { new Claim("name",model.UserName) }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var cliamsPrincipal = new ClaimsPrincipal(claimsIdentity); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, cliamsPrincipal); return RedirectToAction("Index", "Home"); } return RedirectToAction("Index"); }
本文主要讲了magration的操做和identity身份的验证
源码:https://github.com/byniqing/AspNetCore-identity
参考资料
https://docs.microsoft.com/en-us/aspnet/core/migration/proper-to-2x/?view=aspnetcore-2.2
https://www.cnblogs.com/jqdy/p/5941248.html
https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/cli/dotnet#dotnet-ef-migrations-remove