C# 我可以迁移到实体框架中未迁移而创建的数据库吗?
我创建了一个桌面应用程序,它使用SQL CE 4.0和实体框架以及代码优先模式。所以,最初我在一个系统上安装了这个应用程序,它运行得很好 现在,我向模型类添加了一些属性,因此为此,我使用C# 我可以迁移到实体框架中未迁移而创建的数据库吗?,c#,entity-framework,ef-code-first,sql-server-ce,entity-framework-migrations,C#,Entity Framework,Ef Code First,Sql Server Ce,Entity Framework Migrations,我创建了一个桌面应用程序,它使用SQL CE 4.0和实体框架以及代码优先模式。所以,最初我在一个系统上安装了这个应用程序,它运行得很好 现在,我向模型类添加了一些属性,因此为此,我使用启用迁移启用了迁移,并使用添加迁移“MyMigration”添加了新迁移。这也是成功的,我能够安装新版本和升级数据库没有任何问题 但现在,当我在没有现有数据库的系统上安装此设置时,它失败了,因此在研究之后,我意识到我需要添加初始迁移,因此,我撤销了模型中的更改,并删除了我的SQLCE数据库文件,添加了初始迁移,然
启用迁移
启用了迁移,并使用添加迁移“MyMigration”
添加了新迁移。这也是成功的,我能够安装新版本和升级数据库没有任何问题
但现在,当我在没有现有数据库的系统上安装此设置时,它失败了,因此在研究之后,我意识到我需要添加初始迁移,因此,我撤销了模型中的更改,并删除了我的SQLCE数据库文件,添加了初始迁移,然后更新数据库
。所以,若我尝试使用未启用迁移而创建的旧数据库更新数据库,那个么它会失败,它会尝试将初始迁移应用到数据库,而我认为它不应该这样做
现在,若我删除旧的数据库文件,然后更新数据库,那个么将创建新的数据库,然后再次将我的更改添加到模型中,并添加预期的迁移
所以,在这之后,我可以在空白系统上安装我的应用程序,但在有旧数据库的系统上失败,也就是说,它不升级数据库
它还尝试应用初始迁移,即再次创建所有表,但失败的原因是,该表已经存在,这不是预期的。您需要的是
update-database
这将相应地更新数据库。请记住,每次添加迁移时,需要更新数据库,当您在其他地方安装系统时,您需要做的是更新数据库以获得与实体框架相称的旧数据库。
如果表已经存在,则需要检查是否进入初始脚本。这不是EF问题,即使您尝试简单地使用表定义运行create数据库脚本,而不检查现有的脚本,也会失败
比如说, 我没有在我的机器上安装任何数据库,我正在使用CREATENEW脚本,其中包含一些表 这是创建表的脚本 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
请注意,我只是创建表,并没有检查对象是否存在,现在,如果我在新机器上使用空数据库运行它,它将不会出错
现在,我尝试用现有对象在现有数据库上运行相同的脚本,可能是为了更新一些表,就像在您的例子中一样,但这里有一个技巧,您的更新脚本将位于此脚本的底部。。。因此,它将首先尝试创建表,如果存在,它将抛出错误
因此,在创建表之前,您需要检查对象是否存在,就像在这个脚本中一样
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
所以,当您尝试运行此操作时,它将跳过表中已存在的对象,并继续执行更新脚本
希望这对您有所帮助……好的,如果您有两次迁移:Initial和MyMigration,现在您有一个旧数据库,它具有第一次迁移表示的更改,但第二次没有,并且它一直尝试应用不必要的第一次迁移,那么您可以通过以下方式解决此问题: 1) 生成完整的迁移脚本(顺便说一句,这可用于创建模型的空白数据库): 2) 此脚本顶部的代码将检查是否存在uu MigrationHistory,如果缺少,则创建它 3A)接下来,它将使用下面的代码检查每个迁移。因为您的数据库已经有了这些,所以您应该注释掉这些行
IF @CurrentMigration < '201702231958592_Initial'
BEGIN
-- objects already exist, but EF doesn't know this
-- CREATE TABLE, etc.
END
4) 每次迁移都会重复步骤3A和3B,因此,如果尚未应用,请将它们保留在那里。注释掉对象更改(如果有)
如果您没有弄乱迁移,那么继续前进EF将足够聪明,可以将更改应用到应用迁移的不同状态下的各种部署中
至于您的安装程序问题,您可以通过ADO.NET调用此脚本,也可以使用代码进行迁移。问题是它检查一个名为migrations的表,我认为它可以从中获取当前squema和更改的信息。如果您在不使用EF的情况下对DB进行了大量更改,那么不知何故,您会遇到大量的克隆冲突 您可以使用来自己做任何事情,并对更改和回滚有更多的控制 例如:
[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");
}
}
我正在通过InstallShield帮助创建的msi安装程序部署我的应用程序,在这种情况下我如何更新数据库?我以前从未使用msi安装程序安装过,但无论如何,entity Framework不应该每次都尝试初始迁移,它应该只做一次。您确实添加了migration->update database,并且数据库应该有migrationhistory表来正确更新,至少实体框架应该是这样工作的。请再次检查我的问题,希望您理解我的问题。我正在100台不同的机器上安装我的安装程序。是的,您如何进行添加迁移?你说你用add migration添加了新的迁移,所以你肯定在某处键入了这个,对吗?为什么在添加迁移后不能运行更新数据库?您的数据库是否有迁移表?使用更新数据库从头开始安装时,迁移表中有多少行?您应该为完成的每个添加迁移获得一行。现在我怀疑旧数据库不会升级,因为它们在迁移表中有不同的行,例如,新数据库可能有init、first update等,但旧数据库可能有init作为第一行,这与应用程序不同,因此失败。我建议您仅使用update database在每台计算机上进行干净的数据库安装,不要进行任何初始数据库安装。请尝试使用命令update database-verbose。。。失败后,向上滚动,您将看到哪个表是正确的
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201702231958592_Initial', N'MyApp.Data.Migrations.Configuration', 0x1F8B08000000
[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");
}
}