繁体   English   中英

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

[英]Code First Migrations - Update-database -script command generated SQL script not working

我必须通过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; }
}

然后我在Post添加了新属性

public string Abstract { get; set; }

然后我跑了

Add-Migration AddPostAbstract

在我的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");
}

之后我执行了这个命令

Update-Database –Verbose

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

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

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

Msg 207,Level 16,State 1,Line 2
列名称“Abstract”无效。

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

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

-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

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

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

但是,请注意-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 ( ...

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

如果你因为你正在生成大型脚本而感到沮丧,那么在任何ALTER TABLE行的末尾放置一个GO是微不足道的,在SSMS中替换,这就像这个答案顶部的那个

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM