EFCore CodeFirst 适配数据库
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就好了,感觉还是有点鸡肋~~~
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/liyouming欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接。