EF6中可以直接根據代碼模型生成數據庫Database.SetInitializer即可
在EFCore中如何實現呢?
這項功能放在了DatabaseFacade對象中,傳入數據庫上下文對象實例化到一個DatabaseFacade對象
可以看到DatabaseFacade有幾個方法:
獲取所有遷移的migraion數據:GetMigrations
獲取待遷移的migration數據 :GetPendingMigrations
獲取已經操作的migration數據:GetAppliedMigrations
適配migration: Migrate
這中間有一個坑:efcore 貌似還不能根據模型生成數據庫,而是要先添加migrations的文件,然后才能適配數據庫
這里我添加了一個XXXX字段,按照正常的流程:我們需要執行命令:
dotnet ef migrations add addxxxxxx
dotnet ef database update

EFCore中的自動適配數據庫的前提是添加好 新增變量的migrations文件,實際上只是efcore只幫助了我們實現了dotnet ef database update的操作
首先先操作下:dotnet ef migrations add addxxxxxx

這里我寫了一個簡單的中間件來說明下:

通過注冊服務,添加usermap引用
/// <summary> /// liyouming add 20180508 /// </summary> /// <typeparam name="T">(context)上下文對象</typeparam> /// <param name="service">擴展服務</param> /// <param name="optionsAction">配置</param> /// <returns></returns> public static IServiceCollection AddEFMigrations<T>(this IServiceCollection service, Action<DbContextOptionsBuilder> optionsAction) where T : DbContext { service.AddDbContext<T>(optionsAction); var serviceProvider = service.BuildServiceProvider(); service.AddSingleton<IEFMigrationsContext>(new EFMigrationsContext(serviceProvider.GetRequiredService(typeof(T)) as DbContext)); return service; }
這里我們需要指導上下文對象T,並將該對象放到自定義的服務 IEFMigrationsContext 去處理下
然后擴展下IApplicationBuilder
public static IApplicationBuilder UseEFMigraions( this IApplicationBuilder builder,string pathstring) { builder.Map(new Microsoft.AspNetCore.Http.PathString(pathstring), app => { app.UseMiddleware<EFMigrationsMiddleware>(pathstring); }); return builder; }
比較簡單,需要map下地址,當我們訪問的時候進入到固定頁面操作
public class EFMigrationsMiddleware { private readonly RequestDelegate _next; private readonly string _pathstring; private IEFMigrationsContext _migrationsContext; public EFMigrationsMiddleware(RequestDelegate next, string pathstring, IEFMigrationsContext migrationsContext) { if (next == null) { throw new Exception(nameof(next)); } _next = next; _pathstring = pathstring; _migrationsContext = migrationsContext; } public async Task Invoke(HttpContext context) { if (context.Request.PathBase == _pathstring) { var list = _migrationsContext.GetPendingMigrations(); _migrationsContext.AutoMigration(); string strli = string.Empty; foreach (var item in list) { strli += "<li>" + item + "</li>"; } await context.Response.WriteAsync("<html><body><ul>" + strli + "</ul></body></html>"); } else { await _next(context); } return; } }
下面直接實現接口方法就ok了,存在待更新的migrations就執行更新
public void AutoMigration() { if (databaseFacade.GetPendingMigrations().Any()) { //執行遷移 databaseFacade.Migrate(); } }
下面來說下使用方式:跟原有的dbcontext使用方式一樣,配置好你的上下文對象配置
注冊服務:
services.AddEFMigrations<UserDbContext>(optionsBuilder => { var _userappsetting = Configuration.Get<UserAppSetting>(); if (_userappsetting == null) { throw new Exception("數據庫連接字符串未配置"); } switch (_userappsetting.DbType) { case 1: optionsBuilder.UseSqlServer(_userappsetting.UserConnectionString, sqlserver => { sqlserver.MigrationsAssembly(_migrationAssablyName); sqlserver.UseRelationalNulls(); sqlserver.UseRowNumberForPaging(); }); break; case 2: optionsBuilder.UseMySQL(_userappsetting.UserConnectionString, mysql => { mysql.MigrationsAssembly(_migrationAssablyName); mysql.UseRelationalNulls(); }); break; default: optionsBuilder.UseSqlServer(_userappsetting.UserConnectionString, sqlserver => { sqlserver.MigrationsAssembly(_migrationAssablyName); sqlserver.UseRelationalNulls(); sqlserver.UseRowNumberForPaging(); }); break; } });
添加Configure
app.UseEFMigraions("/Migrations");
下面訪問下:/Migrations ,這里上面的代碼中我先獲取了待更新的migraions 方便驗證,這里可以看到待驗證的migraions是我新添加 addxxxxxxx

下面我們來檢查數據生成情況:
已經生成了 XXXXX字段
如果能不操作dotnet ef migrations add addxxxxxx就好了,感覺還是有點雞肋~~~
