• 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就好了,感觉还是有点鸡肋~~~

  • 相关阅读:
    Google Map API基本概念(转载)很好的例子
    Sql Exception Handling & Throw Exception
    幸福人生讲座(十):五伦中哪一伦最重要?
    Delete Database Log
    杨澜语录
    余世雄 如何提升职场“执行力”
    红楼女梦
    假如我真的看透了
    余世维 有效沟通
    习惯修养
  • 原文地址:https://www.cnblogs.com/liyouming/p/9010027.html
Copyright © 2020-2023  润新知