我可以迁移到在Entity框架中无迁移创建的数据库吗?

时间:2017-03-16 06:52:55

标签: c# entity-framework ef-code-first sql-server-ce ef-migrations

我创建了一个桌面应用程序,它使用 SQL CE 4.0 实体 框架代码第一个模式。所以,最初我在系统上安装了应用程序,它工作正常。

现在我向模型类添加了一些属性,因此为此我使用Enable-Migrations启用了迁移,并使用Add-Migration "MyMigration"添加了新的迁移。这也是成功的,我能够毫无问题地安装新版本和升级数据库。

但是现在当我在没有现有数据库的系统上安装此设置时,它就失败了,所以经过研究我意识到我需要添加初始迁移所以,我撤销了模型中的更改并删除了我的SQLCE数据库文件,添加了初始迁移,然后是Update-Database。因此,如果我尝试使用在没有启用迁移的情况下创建的旧数据库来更新数据库,那么它会失败,它会尝试将初始迁移应用到数据库,而不应该根据我这样做。

现在,如果我删除旧数据库文件,然后删除Update-Database,则会创建新的数据库,然后再次将我的更改添加到模型并添加预期的迁移。

所以在此之后,转变我能够在空白系统上安装我的应用程序,但是在具有旧数据库的系统上失败,即它不会升级数据库。

它也尝试应用初始迁移,即再次创建所有表并且无法说明表已存在,这是不期望的。

4 个答案:

答案 0 :(得分:2)

问题是它检查了一个名为Migrations的表,其中我认为它获取当前squema和更改的信息。如果你在不使用EF的情况下对数据库进行了大量的更改,那么当你发生大量的冲突时,你会发现这一点。

您可以使用acts as a wrapper自行完成所有操作并更好地控制更改和回滚

示例:

 [Migration(201610250659)]
public class _201610250659_AddedMinimumValue_Prices : Migration
{
    public override void Up()
    {
        Alter.Table("Prices")
            .AddColumn("MinimunValue").AsInt32().NotNullable().WithDefaultValue(1);
    }

    public override void Down()
    {
        Delete.Column("MinimunValue")
            .FromTable("Prices");
    }
}

答案 1 :(得分:1)

您需要的是

update-database 

这将相应地更新数据库。只需记住每次添加迁移时需要更新数据库,当您在其他地方安装系统时,您只需要执行更新数据库以使旧数据库与实体框架相同。

答案 2 :(得分:1)

如果表已经存在,您需要检查是否已进入初始脚本。它不是EF问题,即使您尝试简单地使用表定义运行创建数据库脚本而不检查现有数据库脚本,它也会失败。

例如,

我没有在我的机器上安装任何数据库,而且我已经创建了带有一些表格的新脚本..

所以这是创建表的脚本

    USE [TestStudent]
GO
/****** Object:  Table [dbo].[EmployeeInformation]    Script Date: 18-03-2017 19:12:40 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[EmployeeInformation](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,
    [Designation] [nvarchar](50) NULL,
 CONSTRAINT [PK_EmployeeInformation] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[sample]    Script Date: 18-03-2017 19:12:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[sample](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [TableId] [int] NULL,
 CONSTRAINT [PK_sample] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

请注意,我只创建不检查对象存在的表,现在如果我在具有空白数据库的新机器上运行它,它将运行而不会出错。

enter image description here

现在,我尝试在现有数据库上运行相同的脚本,现有的对象可能用于更新一些表,就像你的情况一样,但这里的诀窍,你的更新脚本将在这个底部......所以它将首先尝试创建表格,如果存在,它将引发错误..

enter image description here

因此您需要在创建表之前检查对象是否存在,例如在此脚本中...

    USE [TestStudent]
GO
/****** Object:  Table [dbo].[EmployeeInformation]    Script Date: 18-03-2017 19:22:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[EmployeeInformation]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[EmployeeInformation](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](50) NULL,
    [LastName] [nvarchar](50) NULL,
    [Designation] [nvarchar](50) NULL,
 CONSTRAINT [PK_EmployeeInformation] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
/****** Object:  Table [dbo].[sample]    Script Date: 18-03-2017 19:22:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sample]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[sample](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [TableId] [int] NULL,
 CONSTRAINT [PK_sample] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

因此,当您尝试运行此操作时,它将跳过表中已存在的对象将继续执行更新脚本...

enter image description here

希望这会有所帮助...

答案 3 :(得分:1)

好的,如果你有2个迁移:初始和MyMigration现在你有一个旧数据库,它具有第一次迁移所代表的变化,但不是第二次迁移,并且它一直试图应用不需要的第一次迁移 - 然后你可以这样解决它:

1)生成完整的迁移脚本(顺便说一句,这可用于创建模型的空白数据库):

Update-Database -Script -SourceMigration: $InitialDatabase

2)此脚本顶部的代码将检查__MigrationHistory是否存在,如果缺少则创建它。

3A)接下来,它将使用如下代码检查每次迁移。由于您的数据库已有这些,您应该对这些行进行注释。

IF @CurrentMigration < '201702231958592_Initial'
BEGIN
     -- objects already exist, but EF doesn't know this
     -- CREATE TABLE, etc.
END

3B)实体框架会将记录插入__MigrationHistory,因此它知道已应用此迁移。不要评论这一行! (长十六进制字符串表示模型)。

INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201702231958592_Initial', N'MyApp.Data.Migrations.Configuration',  0x1F8B08000000

4)每次迁移都会重复步骤3A和3B,如果没有应用,请将它们留在那里。如果对象发生了变化,请将其注释掉。

如果您没有考虑迁移,那么向前迈进EF将足够聪明,可以将更改应用于应用迁移的不同状态中的各种部署。

关于安装程序问题,您可以通过ADO.NET调用此脚本,也可以使用DbMigrator进行代码迁移。