本文为本人日记,用于个人记录。
The model backing the 'XXXXContext' context has changed since the database was created. Consider using Code First Migrations to update the database
接收古董项目10年前的代码,摊上传说中的祖传代码,踩坑无数,今天说说其中一个坑。个人是不喜欢EF的,做个Demo还行,真实项目上使用灵活性太差。
古董代码环境:VS2010+EF4.1+WCF+C#+SQLServer2008+WinForm+C++_硬件API+硬件
需求:数据库不能重建,在老库(已有数据)某两个数据表增加几个字段。(注意需求是已有数据)
工程组成:Model层、WCFService层、WinFormClient层
针对想当然做法:Model层对表对应实体中增加字段、数据库中手动以SQL增加两个列、更新WCF引用,坐等测试通过
运行现象:WinFormClient调用WCF,在WCFService层非改动表使用using (XXDBContext db = new XXDBContext())抛出异常,异常消息:The model backing the 'XXXXContext' context has changed since the database was created. Consider using Code First Migrations to update the database
不好,大事不妙,悟空坏了蟠桃大会,后果很严重,黎叔很生气。上下求索的路子曲折,这里不赘述了。
关键思想:CodeFirst模式EF代码与数据库形成了绑定关系,手动修改数据库增加列后,EF不认。通过EF CodeFirst迁移方式,让EF对数据表字段新增修改。
程序包管理控制台再次输入启用迁移的命令Enable-Migrations,本例前面尝试过几次所以使用Enable-Migrations -Force
PM> Enable-Migrations Migrations have already been enabled in project 'EntityModel'. To overwrite the existing migrations configuration, use the -Force parameter. PM> Enable-Migrations -Force Code First Migrations enabled for project EntityModel.
把实体类工程EntityModel设置为启动项目
再次执行命令Add-Migration AddCol_Table。如果仍报数据库连接错误,则可尝试使用“
Add-Migration AddCol_Table -ConnectionString "Data Source=127.0.0.1;Initial Catalog=xxx;user id=xx;password=xx"
位于命令管道位置 1 的 cmdlet Add-Migration
请为以下参数提供值:
ConnectionProviderName: System.Data.SqlClient
Scaffolding migration 'AddCol_C_RoutinePower'.
”
此命令执行后会在当前工程下创建一个202008280232342_AddCol_Table.cs文件,文件代码大致类似如下 namespace EntityModel.Migrations { using System.Data.Entity.Migrations; public partial class AddCol_Table: DbMigration { public override void Up() { CreateTable( "xxx", c => new { xxxx }) .PrimaryKey(t => t.xxx); } public override void Down() { DropIndex("xxx", new[] { "cc" }); DropForeignKey("xxx", "bb", "aa"); DropTable("xxx"); } } }
我们不需要上面的删除表和新增表代码,修改代码为新增字段删除字段
namespace EntityModel.Migrations { using System.Data.Entity.Migrations; public partial class AddCol_C_PowerCalibrateBase : DbMigration { public override void Up() { //下面的代码是wdh手动添加的。 AddColumn("dbo.xxx", "aaa", c => c.Double(nullable: null)); } public override void Down() { DropColumn("dbo.xxx", "aaa"); } } }
输入命令,用指定连接字符串将上述代码更新到数据库。命令:update-database -verbose -ConnectionString "Data Source=127.0.0.1;Initial Catalog=xxxx;user id=xxx;password=xxx",在提示后输入“System.Data.SqlClient”
PM> update-database -verbose -ConnectionString "Data Source=127.0.0.1;Initial Catalog=xxxx;user id=xxx;password=xxx" 位于命令管道位置 1 的 cmdlet Update-Database 请为以下参数提供值: ConnectionProviderName: System.Data.SqlClient Using NuGet project 'EntityModel'. Using StartUp project 'EntityModel'. Target database is: 'xxx' (DataSource: 127.0.0.1, Provider: System.Data.SqlClient, Origin: Explicit). Applying explicit migrations: [202008280232342_AddCol_Table]. Applying explicit migration: 202008280232342_AddCol_xxx. ALTER TABLE [dbo].[xxx] ADD [xxx] [float] ALTER TABLE [dbo].[xxx] ADD [xxx] [float] CREATE TABLE [__MigrationHistory] ( [MigrationId] [nvarchar](255) NOT NULL, [CreatedOn] [datetime] NOT NULL, [Model] [varbinary](max) NOT NULL, [ProductVersion] [nvarchar](32) NOT NULL, CONSTRAINT [PK___MigrationHistory] PRIMARY KEY ([MigrationId]) ) BEGIN TRY EXEC sp_MS_marksystemobject '__MigrationHistory' END TRY BEGIN CATCH END CATCH [Inserting migration history record] PM>
检查数据库中表字段是否已经新增成功了。
如果update-database命令执行未报错,前面已执行过多次,但数据库中对应的表字段未加上。处理办法:将[dbo].[__MigrationHistory]表中的与当前记录重复202008280307106_AddCol_Table记录删除,然后重新执行一遍update-database命令。
打开客户端,重新调用WCF,OK,通过。
官方参考
https://docs.microsoft.com/zh-cn/ef/ef6/modeling/code-first/migrations/?redirectedfrom=MSDN
参考:https://www.cnblogs.com/chenwolong/p/migrations.html
https://www.cnblogs.com/haogj/archive/2012/02/17/2356537.html
https://www.cnblogs.com/Laimic/articles/4318707.html
https://blog.csdn.net/hit_why/article/details/72778785?utm_source=blogxgwz28
nuget包:
https://www.nuget.org/packages/EntityFramework/