代码优先迁移 - Update-database -script命令生成的SQL脚本无法正常工作

Shi*_*mar 4 entity-framework ef-migrations entity-framework-5

我必须通过Entity Framework 5使用以下模型创建数据库:

public class Post
{
        public int PostId { get; set; }
        [MaxLength(200)]
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我添加了新的属性 Post

public string Abstract { get; set; }
Run Code Online (Sandbox Code Playgroud)

然后我跑了

Add-Migration AddPostAbstract
Run Code Online (Sandbox Code Playgroud)

在我的Migrations文件夹中创建了以下类,之后我通过添加一个SQL语句修改了这个文件

//201308300714477_AddPostAbstract.cs
public override void Up()
{
                AddColumn("dbo.Posts", "Abstract", c => c.String());
                Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
}

public override void Down()
{
    DropColumn("dbo.Posts", "Abstract");
}
Run Code Online (Sandbox Code Playgroud)

之后我执行了这个命令

Update-Database –Verbose
Run Code Online (Sandbox Code Playgroud)

它更新了我的数据库并返回了这个SQL查询:

ALTER TABLE [dbo].[Posts] ADD [Abstract] [nvarchar](max)
UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL
Run Code Online (Sandbox Code Playgroud)

现在我Abstract已从表中删除了列,并尝试在SQL中手动执行上述查询,此时它向我显示以下错误.

消息207,级别16,状态1,行2
无效的列名称"抽象".

我的问题是为什么这个查询不在SQL中执行,即使这个查询是通过迁移生成的?

或者有没有办法通过迁移生成的脚本运行这样的多个查询.

And*_*own 12

-Verbose输出只显示发言摘要.如果在SQL Server Management Studio中手动运行命令,则需要GO在两个语句之间:

ALTER TABLE [dbo].[Posts] ADD [Abstract] [nvarchar](max)
GO
UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL
Run Code Online (Sandbox Code Playgroud)

快速解决方法是执行以下操作:

  • update-database -script
  • 然后使用Sql Server management Studio在生成的脚本中执行以下搜索和替换:
    • 查找:^{:b*}{{INSERT|UPDATE|SELECT|DELETE}.+}(此发现任何CRUD语句)
    • 替换为:\1GO\n\1\2\n(保持缩进,并添加GO之前的任何CRUD语句)
    • 查找选项:使用正则表达式

但是,请注意,-Verbose它不会提供您想要的输出,您需要输出-Script,或者您将丢失__MigrationHistory历史表的插入数据,这可能导致应用程序在运行时抛出错误(有关详细信息,请参见下文) .

细节

您对以下有关MSDN Code First Migrations页面上的信息的评论很有意思.页面实际指出(在"获取SQL脚本"部分下)

运行Update-Database命令,但这次指定-Script标志

如果你这样做,你会看到类似的东西:

ALTER TABLE [dbo].[Posts] ADD [Abstract] [nvarchar](max)
UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL
INSERT INTO [__MigrationHistory] ([MigrationId], [Model], [ProductVersion]) VALUES ( ...
Run Code Online (Sandbox Code Playgroud)

INSERT很重要 - 这就是您的应用程序中的EF将如何知道它使用最新的db版本(因此将运行而不是向您显示错误).但是,仍然缺少GO命令.因此,SQL Server尝试将3行编译为单个批处理并失败.

添加所需的GO语句后,您仍然可以通过以下方式将其包含在单个事务中:

BEGIN TRANSACTION;
BEGIN TRY
   --Your migration code, with GO statements
END TRY
BEGIN CATCH
  SELECT 
    ERROR_NUMBER() AS ErrorNumber
    ,ERROR_SEVERITY() AS ErrorSeverity
    ,ERROR_STATE() AS ErrorState
    ,ERROR_PROCEDURE() AS ErrorProcedure
    ,ERROR_LINE() AS ErrorLine
    ,ERROR_MESSAGE() AS ErrorMessage;

  IF @@TRANCOUNT > 0
    ROLLBACK TRANSACTION;
END CATCH;

IF @@TRANCOUNT > 0
  COMMIT TRANSACTION;
GO
Run Code Online (Sandbox Code Playgroud)

如果您因为生成大型脚本而感到沮丧,那么在SSMS中放置GO任何ALTER TABLE行的末尾都是微不足道的,这将类似于此答案顶部的那个


归档时间:

查看次数:

8732 次

最近记录:

10 年,1 月 前