4

我創造了一個桌面應用程序它採用SQL CE 4.0實體框架的Code First模式。所以,最初我在系統上安裝了應用程序,它運行良好。我可以遷移到在Entity框架中沒有遷移的情況下創建的數據庫嗎?

現在我向模型類添加了一些屬性,因此爲此目的,我使用Enable-Migrations啓用了遷移,並使用Add-Migration "MyMigration"添加了新的遷移。這也是成功的,我能夠安裝新版本和升級數據庫而沒有任何問題。

但現在當我的系統上安裝此設置沒有現有的數據庫,然後失敗了,所以學習後,我意識到,我需要添加初始遷移所以,我撤銷模型的變化,也刪除了我的SQLCE數據庫文件,添加了初始遷移,然後Update-Database。因此,如果我嘗試使用在未啓用遷移的情況下創建的舊數據庫來更新數據庫,那麼它會失敗,它會嘗試將初始遷移應用於數據庫,而不應該依據我的數據庫。

現在,如果我刪除舊數據庫文件,然後更新數據庫然後創建新數據庫,然後再次將我的更改添加到模型並添加預期的遷移。

因此,在此之後,我可以在空白系統上安裝我的應用程序,但它在具有舊數據庫的系統上失敗,即它不升級數據庫。

它也嘗試應用初始遷移,即再次創建所有表,並且失敗,說明,該表已存在這不是預期的。

+0

嘗試使用命令更新數據庫-verbose ...在失敗後向上滾動,您將看到哪個表導致問題 –

+0

Update-Database可以工作,但是,當我在任何客戶端系統上構建安裝文件並進行部署時,它會嘗試應用InitialCreate遷移並重新創建所有表,從而導致出錯作爲** XYZ表已經存在** –

回答

1

你需要的是

update-database 

這將相應地更新數據庫。只需記住,每次添加遷移時都需要更新數據庫,並且在其他位置安裝系統時,您只需要執行更新數據庫即可使舊數據庫與實體框架保持一致。

+0

我通過在InstallShield的幫助下創建的msi安裝程序部署我的應用程序,在那種情況下如何更新數據庫? –

+0

我從來沒有安裝msi安裝程序,但無論如何,實體framewok不應該嘗試每次初始遷移,它應該只做一次。你做添加遷移 - >更新數據庫和數據庫應該有migrationhistory表更新正常,至少這是實體框架的工作方式 – Mindless

+0

請再次通過我的問題,希望你明白我的問題。我正在100臺不同的機器上安裝我的設置。 –

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

希望這有助於...

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在代碼中進行遷移。

2

問題是它檢查一個名爲Migrations的表,其中我認爲它獲取當前squema的信息並且更改了。如果您在不使用EF的情況下進行數據庫更改,不知怎的,當很多clonflicts會發生時,您會發現一個問題。

您可以使用fluent migrations自己做的一切,有變化更多的控制和回滾

例子:

[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"); 
    } 
} 
相關問題