Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我可以迁移到实体框架中未迁移而创建的数据库吗?_C#_Entity Framework_Ef Code First_Sql Server Ce_Entity Framework Migrations - Fatal编程技术网

C# 我可以迁移到实体框架中未迁移而创建的数据库吗?

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数据库文件,添加了初始迁移,然

我创建了一个桌面应用程序,它使用SQL CE 4.0实体框架以及代码优先模式。所以,最初我在一个系统上安装了这个应用程序,它运行得很好

现在,我向模型类添加了一些属性,因此为此,我使用
启用迁移
启用了迁移,并使用
添加迁移“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");
    }
}