簡體   English   中英

實體框架代碼優先:如何手動更新數據庫?

[英]Entity Framework Code-First: How to manually update the database?

我構建了一個小 WPF 演示應用程序,它使用 EF Code-First 將其數據保存在 SQL CE 4.0 DB 中。 除非我從 model object 中刪除一個屬性,否則它工作正常。 例如,如果我從這個 class 中刪除“HosteBy”......

public class Dinner
{
    public int DinnerID { get; set; }
    public string Title { get; set; }   
    public DateTime EventDate { get; set; }
    public string Address { get; set; }
    public string HostedBy { get; set; }

    public virtual ICollection<RSVP> RSVPs { get; set; }
}

...它拋出這個異常:

自數據庫創建以來,支持“NerdDinners”上下文的 model 已更改。 手動刪除/更新數據庫,或使用 IDatabaseInitializer 實例調用 Database.SetInitializer。 例如,DropCreateDatabaseIfModelChanges 策略將自動刪除並重新創建數據庫,並可選擇使用新數據為其播種。

即使從數據庫中手動刪除了“HosteBy”字段,該錯誤仍然存在。 我在這里想念什么? 我必須刪除/截斷數據庫還是有其他解決方案?

在您更改 Code First Model 的第一個場景中,在您手動修改數據庫之前,答案是打開 (Nuget) Package 管理器控制台並鍵入:

update-database -verbose

除了 - 因為在這種情況下您正在刪除一個列,這將報告它即將刪除某些內容,並且如果您沒有明確表示可以,它不會刪除任何內容。 所以你輸入:

update-database -f -verbose

現在這將刪除您在 Model 中的列。 -verbose告訴你它運行的 SQL。 如果您害怕讓它刪除東西,而是在 SQL 運行之前檢查它,請使用:

更新數據庫 -f -腳本

這會將 SQL 轉儲到您可以查看的腳本中,然后自己手動運行。

在您繼續手動刪除數據庫中的列的情況下,您現在手頭有一個更復雜的場景; 此處另一個答案中描述的 EdmMetadata 表包含整個數據庫的 hash 現在與數據庫本身不匹配。 您可以運行手動 SQL 以通過檢查您之前擁有的內容和您的數據庫當前的外觀,將數據庫返回到實體框架所期望的方式(手動修改之前的方式,使其與哈希一致)。

如果這不可行,那么您現在處於 Entity Framework Code First 中最丑陋的部分。 您需要消除 hash 表並將數據庫反向工程為代碼文件。

hash 表名取決於 EF 的版本。 在您所詢問的舊版 EF4 中,它稱為 EdmMetadata。 在較新的 EF5 中,它稱為 __MigrationHistory(如果您正在查看 SQL Server Management Studio,則在數據庫中的系統表下)。 你需要把它擦掉。

第二步(將數據庫逆向工程為代碼)的好消息是,Microsoft 已經發布了一個測試版工具,可以為您執行此操作。

對數據庫進行逆向工程和 EF Power Tools 演練

您可以跳過那里的許多第一步,因為他們只是設置數據庫並添加一些廢話,以便他們可以演示您需要做什么:對數據庫進行逆向工程。

更新:

使用手動遷移來解決這種情況也是可行的。 備份數據庫,然后運行:

add-migration WhateverYouWantToCallThis

需要運行的對 db EF Migrations 的修改將出現在生成的 C# 命令中。 現在由您來修改它們,以解決它試圖做的問題(例如嘗試刪除已刪除的列),並落實未來需要的事情(例如添加回您在 model 中仍有一個表,但您在數據庫中手動刪除了)。

添加並運行update-database -f后,EF Code First 將相信您已按照需要的方式更新了數據庫,並根據最終結果更新其 hash。 如果您進行了正確的更改,您現在可以正常進行遷移。 如果這仍然導致錯誤,您通常可以將手動遷移的命令復制到某處並將其刪除,從備份中恢復數據庫,再次添加手動遷移並重試。 最壞的情況是您求助於上面的逆向工程步驟。

如果您的數據庫包含一些名為EdmMetadata的奇怪表,則您的上下文使用一些非常基本的數據庫版本控制。 When it created the database it stored a hash of your model into this table and each time it builds a model for your application (first time you use the context after restarting your application) it again computes the hash and compares it with the hash stored in那張桌子。 這意味着您的 model 中的任何更改都將導致不同的 hash 和 EF 將對您看到的異常做出反應。 手動更改數據庫對您沒有幫助,因為該表包含仍然是舊的。

解決方案是:

  • 刪除此版本控制。 它需要按照此處所述刪除IncludeMetadataConvention
  • 更新 hash。 It would require to reverse engineer the algorithm for hash computation (for example by Red Gate .NET Reflector, JetBrains dotPeek, SharpDevelop ILSpy or Telerik JustDecompile) and computing new hash from compiled model (or using reflection to read internal property from DbCompiledModel.ModelHash with already計算哈希),您將存儲在EdmMetadata表中。
  • 手動刪除數據庫並讓 EF 創建一個新數據庫 - 您將丟失所有數據
  • 將初始化程序設置為DropCreateDatabaseIfModelChanges - 如果您更改 model,它將自動刪除數據庫並創建一個新數據庫 - 您將丟失所有數據

查看本文關於使用現有數據庫進行代碼優先遷移的部分
http://msdn.microsoft.com/en-us/data/dn579398

有時您的項目和數據庫可能會不同步。 因此,您可能必須根據現有數據庫重新同步您的架構。



1) 基於現有架構創建遷移:
添加遷移初始創建

2) 之后運行 Update-Database 以將條目添加到 _MigrationsHistory 表中,以指示遷移已完成到現有架構。

使用 Code First 時需要記住的三個簡單事項

  1. 啟用遷移
  2. 添加遷移
  3. 更新數據庫

一切都是不言自明的。

您需要在 Package Manager Console 上手動運行這些命令。 我遲到了,但希望它會有所幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM