西安建站套餐,在俄罗斯做网站需要多少卢布,网站设计机构,韶关市住房和城乡建设局网站【导读】嗯#xff0c;距离上一次写博文已经过去近整整十个月#xff0c;还是有一些思考#xff0c;但还是变得懒惰了#xff0c;心思也不再那么专注#xff0c;有点耗费时间#xff0c;学习也有点停滞不前#xff0c;那就顺其自然#xff0c;随心所欲吧#xff0c;等…【导读】嗯距离上一次写博文已经过去近整整十个月还是有一些思考但还是变得懒惰了心思也不再那么专注有点耗费时间学习也有点停滞不前那就顺其自然随心所欲吧等哪天心血来潮想写了就写写。模型自动更新上一般团队人数很少时使用EF Core内置迁移基本已满足满足的基本前提首先要生成迁移文件然后和数据库进行对比但团队人数一多迁移文件等等涉及提交冲突等等所以大部分情况下我个人认为EF Core迁移基本没啥用这玩意用不起来尤其涉及到版本分支很多情况下切换不同分支所使用的数据可能也会不同我们常用MySql数据库同时适配了人大金仓数据库、高斯数据库GaussDb for opengauss其对应的表结构有一些差异性列类型也会有很大差异性这对开发人员和测试人员来讲就是深深的折磨和痛苦大部分时间会花在保持数据库表结构和模型一致否则要么运行不起来要么测试功能各种有问题所以想想通过自动化方式来解决这个问题本文还是分上下两篇写好了。那么解决此问题的思路是怎样的呢同时适配多套数据库重写一套那是不阔能的既然我们可以通过dotnet ef命令来进行迁移通过和数据库表结构进行对比从而生成迁移文件迁移文件包含即将要执行的差异性脚本从这个角度来看的话我们从迁移类反堆即可得到生成的脚本以及和数据库进行对比操作方法初步设想理论上应该行得通只需花时间了解下源码就好通过前期两天的啃源码最终啃出百把行代码即可自动更新模型到数据库当然这个过程中还涉及一些要考虑的细节我们一一再叙。接下来我们以MySql为例讲讲整个过程其他数据库依葫芦画瓢就好首先甩出如下代码var services new ServiceCollection();services.AddEntityFrameworkMySql();services.AddEntityFrameworkDesignTimeServices();services.AddDbContextEfCoreDbContext((serviceProvider, options)
{options.UseInternalServiceProvider(serviceProvider);options.UseMySql(serverlocalhost;Port3306;Databasetest;Usernameroot;Passwordroot;,ServerVersion.AutoDetect(serverlocalhost;Port3306;Databasetest;Usernameroot;Passwordroot;));
});services.AddScopedIDatabaseModelFactory, MySqlDatabaseModelFactory();var serviceProvider services.BuildServiceProvider();EF Core有属于它自己的容器所以我们将全局容器和上下文所属容器做了区分同时呢我们将迁移中要用到的操作依赖也手动添加比如上面的设计服务存在于 Microsoft.EntityFrameworkCore.Design 包内最后将获取数据库表结构模型工厂手动注入即MySqlDatabaseModelFactory。接下来我们要获取模型定义以及属性一些定义等等也就是我们最终要生成的目标模型结构using var scope _serviceProvider.CreateScope();var currentServiceProvider scope.ServiceProvider;var context (DbContext)currentServiceProvider.GetRequiredServiceT();var connectionString context.Database.GetDbConnection().ConnectionString;var targetModel context.GetServiceIDesignTimeModel().Model.GetRelationalModel();if (targetModel null)
{return Enumerable.EmptyMigrationOperation().ToList();
}接下来则是获取数据库表结构也就是数据库模型var databaseFactory currentServiceProvider.GetServiceIDatabaseModelFactory();var factory currentServiceProvider.GetServiceIScaffoldingModelFactory();var tables context.Model.GetEntityTypes().Select(e e.GetTableName()).ToList();if (!tables.Any())
{return Enumerable.EmptyMigrationOperation().ToList();
}// 仅查询当前上下文模型所映射表否则比对数据库表差异时将会删除非当前上下文所有表
var databaseModel databaseFactory.Create(connectionString, new DatabaseModelFactoryOptions(tables: tables));if (databaseModel null)
{return Enumerable.EmptyMigrationOperation().ToList();
}这里稍微需要注意的是若是有多个不同上下文肯定只查询当前上下文所对应的模型结构不然最后生成的脚本会将其他上下文对应的表结构给删除。紧接着我们需要将数据库模型转换为上下文中的模型即类型一致转换这就演变成了我们的源模型var model factory.Create(databaseModel, new ModelReverseEngineerOptions());if (model null)
{return Enumerable.EmptyMigrationOperation().ToList();
}var soureModel model.GetRelationalModel();接下来自热而然就进行源模型和目标模型差异性比对得到实际要进行的迁移操作var soureModel model.GetRelationalModel();//TODO Compare sourceModel vs targetModelvar modelDiffer context.GetServiceIMigrationsModelDiffer();var migrationOperations modelDiffer.GetDifferences(soureModel, targetModel);那接下来问题来了拿到差异性迁移操作后我们应该怎么处理呢留着各位思考下本文给出了自动更新模型思路以及整个完整实现逻辑剩余内容我们下篇再叙主要是没心情写写不下去了今天我们就到此为止~