Fork me on GitHub

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;
                }
            });
AddEFMigrations

添加Configure

 app.UseEFMigraions("/Migrations");

下面访问下:/Migrations ,这里上面的代码中我先获取了待更新的migraions 方便验证,这里可以看到待验证的migraions是我新添加 addxxxxxxx

下面我们来检查数据生成情况: 已经生成了 XXXXX字段

 

 

 如果能不操作dotnet ef migrations add addxxxxxx就好了,感觉还是有点鸡肋~~~

 

posted @ 2018-05-08 18:14  龙码精神  阅读(1924)  评论(0编辑  收藏  举报