代码之家  ›  专栏  ›  技术社区  ›  R. Schreurs Rohith

实体框架迁移的“列名无效”

  •  1
  • R. Schreurs Rohith  · 技术社区  · 6 年前

    我有一个问题,用一个迁移更新一个数据库,这个迁移将一个列添加到一个表中并为它赋值。我把这个问题简化成一个很简单的案子。

    模型如下:

    public class Model
    {
        public int Id { get; set; }
    
        public int Col2 { get; set; }
    }
    

    这是上下文:

    public class Context : DbContext
    {
        public DbSet<Model> Models { get; set; }
    }
    

    首先,我启用了迁移,创建了一个初始迁移并创建了一个数据库。

    PM> Enable-Migrations
    PM> Add-Migration -Name Initial
    PM> Update-Database
    

    然后,我扩展了我的模型:

    public int Col3 { get; set; }
    

    并创建了一个新的迁移:

    PM> Add-Migration -Name AddedCol3
    

    我修改了迁移以更新col3中的值,请参见对sql()的调用:

    public override void Up()
    {
        AddColumn("dbo.Models", "Col3", c => c.Int(nullable: false));
        Sql("update dbo.Models set Col3 = Col2");
    }
    
    public override void Down()
    {
       DropColumn("dbo.Models", "Col3");
    }
    

    当我使用此迁移更新数据库时,会得到:

    msg 207,级别16,状态1,行2列名“col3”无效。

    生成的脚本是:

    ALTER TABLE [dbo].[Models] ADD [Col3] [int] NOT NULL DEFAULT 0
    update dbo.Models set Col3 = Col2
    -- Removed update to migration history.
    

    显然,sql server不能一批处理alter表和更新。

    我试着加上 SQL("GO"); 但这会导致错误:

    参数“sql”不能为空或仅包含空格。

    当尝试更新时。

    如何使用迁移来实现这一点。我希望我的up()和down()方法一致地更新数据库。

    2 回复  |  直到 6 年前
        1
  •  0
  •   R. Schreurs Rohith    6 年前

    我通过添加一个伪sql语句找到了解决方法:

    Sql("select 1\nGO");
    

    结果脚本是:

    ALTER TABLE [dbo].[Models] ADD [Col3] [int] NOT NULL DEFAULT 0
    GO
    
    select 1
    
    update dbo.Models set Col3 = Col2
    

    请注意 GO 语句已自动移动到另一个位置!

    无论如何,该脚本现在已被sql server接受,并且更改将以预期的方式应用。

        2
  •  0
  •   R. Schreurs Rohith    6 年前

    @scsimon提供的解决方案转换为sql语句

    Sql("EXEC('update dbo.Models set Col3 = Col2')");
    

    脚本

    ALTER TABLE [dbo].[Models] ADD [Col3] [int] NOT NULL DEFAULT 0
    EXEC('update dbo.Models set Col3 = Col2')
    

    工作很好。

    我更喜欢这种方法,因为我希望它比ef修改更不容易被证明。

    推荐文章