当前位置: 首页 > news >正文

哈尔滨营销型网站制作合肥网站建设电话咨询

哈尔滨营销型网站制作,合肥网站建设电话咨询,施工企业组织机构框架图,石家庄全网seo在开发涉及到数据库的程序时#xff0c;常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况#xff0c;这时就需要进行数据库迁移。实现数据库迁移有很多种办法#xff0c;从手动管理各个版本的ddl脚本#xff0c;到实现自己的migrator#xff0c;或是使用… 在开发涉及到数据库的程序时常会遇到一开始设计的结构不能满足需求需要再添加新字段或新表的情况这时就需要进行数据库迁移。实现数据库迁移有很多种办法从手动管理各个版本的ddl脚本到实现自己的migrator或是使用Entity Framework提供的Code First迁移功能。Entity Framework提供的迁移功能可以满足大部分人的需求但仍会存在难以分项目管理迁移代码和容易出现context has changed错误的问题。 这里我将介绍ZKWeb网页框架在Fluent NHibernate和Entity Framework Core上使用的办法。可以做到添加实体字段后只需刷新网页就可以把变更应用到数据库。 实现全自动迁移的思路 数据库迁移需要指定变更的部分例如添加表和添加字段。而实现全自动迁移需要自动生成这个变更的部分具体来说需要 获取数据库现有的结构获取代码中现有的结构对比结构之间的差异并生成迁移 这正是Entity Framework的Add-Migration(或dotnet ef migrations add)命令所做的事情接下来我们将看如何不使用这类的命令在NHibernate, Entity Framework和Entity Framework Core中实现全自动的处理。 Fluent NHibernate的全自动迁移 ZKWeb框架使用的完整代码可以查看这里 首先Fluent NHibernate需要添加所有实体的映射类型以下是生成配置和添加实体映射类型的例子。配置类的结构可以查看这里 var db MsSqlConfiguration.MsSql2008.ConnectionString(连接字符串);var configuration Fluently.Configure(); configuration.Database(db); configuration.Mappings(m {m.FluentMappings.Add(typeof(FooEntityMap));m.FluentMappings.Add(typeof(BarEntityMap));... }); 接下来是把所有实体的结构添加或更新到数据库。NHibernate提供了SchemaUpdate这个类可以自动检测数据库中是否已经有表或字段没有时自动添加。使用办法非常简单以下是使用的例子 configuration.ExposeConfiguration(c {    // 第一个参数 false: 不把语句输出到控制台// 第二个参数 true: 实际在数据库中执行语句new SchemaUpdate(c).Execute(false, true); }); 到这一步就已经实现了全自动迁移但我们还有改进的余地。因为SchemaUpdate不保存状态每次都要检测数据库中的整个结构所以执行起来EF的迁移要缓慢很多ZKWeb框架为了减少每次启动网站的时间在执行更新之前还会检测是否需要更新。 var scriptBuilder new StringBuilder(); scriptBuilder.AppendLine(/* this file is for database migration checking, dont execute it */);new SchemaExport(c).Create(s scriptBuilder.AppendLine(s), false);var script scriptBuilder.ToString();if (!File.Exists(ddlPath) || script ! File.ReadAllText(ddlPath)) {    new SchemaUpdate(c).Execute(false, true);onBuildFactorySuccess () File.WriteAllText(ddlPath, script); } 这段代码使用了SchemaExport来生成所有表的DDL脚本生成后和上次的生成结果对比不一致时才调用SchemaUpdate更新。 NHibernate提供的自动迁移有以下的特征使用时应该注意 字段只会添加不会删除如果你重命名了字段原来的字段也会保留在数据库中字段类型如果改变数据库不会跟着改变关联的外键如果改变迁移时有可能会出错 总结NHibernate的自动迁移只会添加表和字段基本不会修改原有的结构有一定的限制但是比较安全。 Entity Framework的全自动迁移 ZKWeb框架没有支持Entity Framework 6但实现比较简单我就直接上代码了。例子 // 调用静态函数放到程序启动时即可// Database是System.Data.Entity.DatabaseDatabase.SetInitializer(new MigrateDatabaseToLatestVersionMyContext, MyConfiguration());public class MyConfiguration : DbMigrationsConfigurationMyContext {    public MyConfiguration() {AutomaticMigrationsEnabled true; // 启用自动迁移功能AutomaticMigrationDataLossAllowed true; // 允许自动删字段危险但是不加这个不能重命名字段} } Entity Framework提供的自动迁移有以下的特征使用时应该注意 如果字段重命名旧的字段会被删除掉推荐做好数据的备份和尽量避免重命名字段外键关联和字段类型都会自动变化变化时有可能会导致原有的数据丢失自动迁移的记录和使用工具迁移一样都会保存在__MigrationHistory表中切勿混用否则代码将不能用到新的数据库中 总结Entity Framework的迁移可以保证实体和数据库之间很强的一致性但是使用不当会导致原有数据的丢失请务必做好数据库的定时备份。 Entity Framework Core的全自动迁移 Entity Framework Core去掉了SetInitializer选项取而代之的是DatabaseFacade.Migrate和DatabaseFacade.EnsureCreated。DatabaseFacade.Migrate可以应用使用ef命令生成的迁移代码避免在生产环境中执行ef命令。DatabaseFacade.EnsureCreated则从头创建所有数据表和字段但只能创建不能更新不会添加纪录到__MigrationHistory。这两个函数都不能实现全自动迁移ZKWeb框架使用了EF内部提供的函数完整代码可以查看这里 Entity Framework Core的自动迁移实现比较复杂我们需要分两步走。 第一步 创建迁移记录__ZKWeb_MigrationHistory表这个表和EF自带的结构相同但这个表是给自己用的不是给ef命令用的第二部 查找最后一条迁移记录和当前的结构进行对比找出差异并更新数据库 第一步的代码使用了EnsureCreated创建数据库和迁移记录表其中EFCoreDatabaseContextBase只有迁移记录一个表。创建完以后还要把带迁移记录的结构保留下来用作后面的对比如果这里不保留会导致迁移记录的重复创建错误。 using (var context new EFCoreDatabaseContextBase(Database, ConnectionString)) {    // We may need create a new database and migration history table// Its done herecontext.Database.EnsureCreated();initialModel context.Model; } 在执行第二步之前还需要先判断连接的数据库是不是关系数据库因为Entity Framework Core以后还会支持redis mongodb等非关系型数据库自动迁移只应该用在关系数据库中。 using (var context new EFCoreDatabaseContext(Database, ConnectionString)) {    var serviceProvider ((IInfrastructureIServiceProvider)context).Instance;    var databaseCreator serviceProvider.GetServiceIDatabaseCreator();    if (databaseCreator is IRelationalDatabaseCreator) {        // Its a relational database, create and apply the migrationMigrateRelationalDatabase(context, initialModel);} else {        // It maybe an in-memory database or no-sql database, do nothing} } 第二步需要查找最后一条迁移记录和当前的结构进行对比找出差异并更新数据库。 先看迁移记录表的内容迁移记录表中有三个字段 Revision 每次迁移都会1Model 当前的结构格式是c#代码ProductVersion 迁移时Entity Framework Core的版本号 Model存放的代码例子如下这段代码记录了所有表的所有字段的定义是自动生成的。后面我将会讲解如何生成这段代码。 using System;using Microsoft.EntityFrameworkCore;using Microsoft.EntityFrameworkCore.Infrastructure;using Microsoft.EntityFrameworkCore.Metadata;using Microsoft.EntityFrameworkCore.Migrations;using ZKWeb.ORM.EFCore;namespace ZKWeb.ORM.EFCore.Migrations{[DbContext(typeof(EFCoreDatabaseContext))]    partial class Migration_636089159513819123 : ModelSnapshot{        protected override void BuildModel(ModelBuilder modelBuilder)        {modelBuilder.HasAnnotation(ProductVersion, 1.0.0-rtm-21431).HasAnnotation(SqlServer:ValueGenerationStrategy, SqlServerValueGenerationStrategy.IdentityColumn);modelBuilder.Entity(Example.Entities.Foo, b {b.PropertyGuid(Id).ValueGeneratedOnAdd();b.Propertystring(Name).IsRequired();});}}} } 接下来查找最后一条迁移记录: var lastModel initialModel;var histories context.SetEFCoreMigrationHistory();var lastMigration histories.OrderByDescending(h h.Revision).FirstOrDefault(); 存在时编译Model中的代码并且获取ModelSnapshot.Model的值这个值就是上一次迁移时的完整结构。不存在时将使用initialModel的结构。编译使用的是另外一个组件你也可以用Roslyn CSharp Scripting包提供的接口编译。 if (lastMigration ! null) {    // Remove old snapshot code and assemblyvar tempPath Path.GetTempPath();    foreach (var file in Directory.EnumerateFiles(tempPath, ModelSnapshotFilePrefix *).ToList()) {        try { File.Delete(file); } catch { }}    // Write snapshot code to temp directory and compile it to assemblyvar assemblyName ModelSnapshotFilePrefix DateTime.UtcNow.Ticks;    var codePath Path.Combine(tempPath, assemblyName .cs);    var assemblyPath Path.Combine(tempPath, assemblyName .dll);    var compileService Application.Ioc.ResolveICompilerService();    var assemblyLoader Application.Ioc.ResolveIAssemblyLoader();File.WriteAllText(codePath, lastMigration.Model);compileService.Compile(new[] { codePath }, assemblyName, assemblyPath);    // Load assembly and create the snapshot instancevar assembly assemblyLoader.LoadFile(assemblyPath);    var snapshot (ModelSnapshot)Activator.CreateInstance(assembly.GetTypes().First(t        typeof(ModelSnapshot).GetTypeInfo().IsAssignableFrom(t)));lastModel snapshot.Model; } 和当前的结构进行对比: // Compare with the newest modelvar modelDiffer serviceProvider.GetServiceIMigrationsModelDiffer();var sqlGenerator serviceProvider.GetServiceIMigrationsSqlGenerator();var commandExecutor serviceProvider.GetServiceIMigrationCommandExecutor();var operations modelDiffer.GetDifferences(lastModel, context.Model);if (operations.Count 0) {    // There no differencereturn; } 如果有差异生成迁移命令(commands)和当前完整结构的快照(modelSnapshot)。上面Model中的代码由这里的CSharpMigrationsGenerator生成modelSnapshot的类型是string。 // There some difference, we need perform the migrationvar commands sqlGenerator.Generate(operations, context.Model);var connection serviceProvider.GetServiceIRelationalConnection();// Take a snapshot to the newest modelvar codeHelper new CSharpHelper();var generator new CSharpMigrationsGenerator(codeHelper,    new CSharpMigrationOperationGenerator(codeHelper),    new CSharpSnapshotGenerator(codeHelper));var modelSnapshot generator.GenerateSnapshot(ModelSnapshotNamespace, context.GetType(),ModelSnapshotClassPrefix DateTime.UtcNow.Ticks, context.Model); 插入迁移记录并执行迁移命令: // Insert the history first, if migration failed, delete itvar history new EFCoreMigrationHistory(modelSnapshot); histories.Add(history); context.SaveChanges();try {    // Execute migration commandscommandExecutor.ExecuteNonQuery(commands, connection); } catch {histories.Remove(history);context.SaveChanges();    throw; } 到这里就完成了Entity Framework Core的自动迁移以后每次有更新都会对比最后一次迁移时的结构并执行更新。Entity Framework Core的迁移特点和Entity Framework一样可以保证很强的一致性但需要注意防止数据的丢失。 写在最后 全自动迁移数据库如果正确使用可以增强项目中各个模块的独立性减少开发和部署的工作量。但是因为不能手动控制迁移内容有一定的局限和危险需要了解好使用的ORM迁移的特点。 写在最后的广告 ZKWeb网页框架已经在实际项目中使用了这项技术目前来看迁移部分还是比较稳定的。这项技术最初是为了插件商城而开发的在下载安装插件以后不需要重新编译主程序不需要执行任何迁移命令就能使用。目前虽然没有实现插件商城也减少了很多日常开发的工作。 如果你有兴趣欢迎加入ZKWeb交流群522083886共同探讨。 原文地址http://www.cnblogs.com/zkweb/p/5859536.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注
http://www.zqtcl.cn/news/397897/

相关文章:

  • 制作php网站用什么软件东莞东坑网站建设
  • 怎样做网站外部样式wordpress爱找主题
  • 自己搭建服务器做网站要多久问答网站如何优化
  • 网站用的服务器小程序拉新项目
  • 建设银行 访问的网站出错珠宝类网站模板
  • 网站百度关键词排名软件xampp里wordpress安装教程
  • 杭州网站设计建立企业网站专业做电脑系统下载网站好
  • 哈尔滨建设网站成本网站建设无广告
  • 发布网站搭建教程云排名网站
  • 无锡大型网站建设房地产景区网站建设方案
  • 自学网站建设工资公众号怎么开通直播功能
  • 网站建设上市公司wordpress park主题
  • 百度网站建设一年多少钱奇艺广州网站建设 熊掌号
  • 建设网站怎么收费标准网站和自媒体都可以做
  • 网站自己怎么做无锡常规网络营销是什么
  • 活泼风格的网站crm免费客户管理系统
  • 网站系统发生错误百度seo灰色词排名代发
  • 免费做名片儿的网站wordpress grace6
  • 有关网站开发的创意四川工程造价信息网官网
  • 网站目录结构北京注册公司地址可以是住宅吗
  • 龙信建设集团网站傻瓜式建站软件下载
  • 在360做网站和百度做网站的区别什么是网站地址
  • 营销型的物流网站模板下载长江设计公司
  • 网站程序制作购买网站域名
  • 网站建设中html下载如何用社交网站开发客户
  • 开设购物网站的方案政务公开和网站建设情况
  • 一台云服务器做多个网站营销型网站的建设重点是什么
  • 泉港网站建设推广服务公司电子商务好就业吗
  • 自己做网站开发如何找客户wordpress 显示 子分类
  • 腾讯邮箱网页版登录宿迁seo公司