EF4.3终于向完美的数据库迁移迈出了重要一步,决定在新项目中使用EF4.3。
问题发生了。
按照 step by step 来没问题,当我第二个迁移为实体增加了一个timestamp时:
/// <summary> /// 行时间戳 /// </summary> [DatabaseGenerated(DatabaseGeneratedOption.Computed)] [Timestamp] public byte[] Timestamp { get; set; }
在NUGET控制台执行
Add-Migration U3
执行成功
生成的更新代码为:
namespace TFFY.Models.Migrations { using System.Data.Entity.Migrations; public partial class U3 : DbMigration { public override void Up() { AddColumn("Tickets", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); AddColumn("TicketItems", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); AddColumn("TicketItemPackages", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); AddColumn("TicketPayments", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); AddColumn("Users", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); AddColumn("Products", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); } public override void Down() { DropColumn("Products", "Timestamp"); DropColumn("Users", "Timestamp"); DropColumn("TicketPayments", "Timestamp"); DropColumn("TicketItemPackages", "Timestamp"); DropColumn("TicketItems", "Timestamp"); DropColumn("Tickets", "Timestamp"); } } }
当继续执行更新数据库时
PM> Update-Database -Verbose Using NuGet project 'TFFY.Models'. Using StartUp project 'TFFY.Models.Test'. Target database is: 'TFFYDBContext' (DataSource: ., Provider: System.Data.SqlClient, Origin: Convention). Applying explicit migrations: [201203070939136_U3]. Applying explicit migration: 201203070939136_U3. ALTER TABLE [Tickets] ADD [Timestamp] rowversion NOT NULL DEFAULT 0x System.Data.SqlClient.SqlException (0x80131904): 不能在数据类型为 timestamp 的列上创建默认值。表 'Tickets',列 'Timestamp'。 无法创建约束。请参阅前面的错误消息。 在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 在 System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async) 在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) 在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery() 在 System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement) 在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement) 在 System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements) 在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements) 在 System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading) 在 System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 在 System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) 在 System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) 在 System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) 在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration) 在 System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore() 在 System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run() 不能在数据类型为 timestamp 的列上创建默认值。表 'Tickets',列 'Timestamp'。 无法创建约束。请参阅前面的错误消息。
看,悲剧发生了。。。
问题显然在于 rowversion NOT NULL DEFAULT 0x
我的临时解决方法
AddColumn("Tickets", "Timestamp", c => c.Binary(nullable: false, fixedLength: true, timestamp: true, storeType: "rowversion")); //把迁移生成代码 相应字段 的 nullable: false 改成 nullable: true AddColumn("Tickets", "Timestamp", c => c.Binary(nullable: true, fixedLength: true, timestamp: true, storeType: "rowversion"));
这样迁移过程中构建迁移sql语句时就会忽略关于默认值的设置
这样生成的数据库虽然把可null设为真,但数据库里生成的时间戳字段仍然为NOT NULL。