25

我的工作,它使用實體框架4.1(第一碼)堅持我們的各種對象的數據庫的項目之後。實體框架4.1的模型支持的背景下已經改變,因爲數據庫創建,創建DB

我在Visual Studio與本地的SQL Express數據庫,我們的詹金斯服務器測試部署致力於代碼,測試服務器。發生這種情況時,我暫時將我的本地連接字符串更改爲指向測試數據庫服務器並運行單元測試以重新創建測試數據庫,以便它與我們的最新實體匹配等。

我最近注意到了我們的測試服務器發出此錯誤:

自創建數據庫以來,支持'EntityFrameworkUnitOfWork'上下文的模型已更改。可以手動刪除/更新數據庫,也可以使用IDatabaseInitializer實例調用Database.SetInitializer。例如,DropCreateDatabaseIfModelChanges策略會自動刪除並重新創建數據庫,並可以選擇使用新數據對其進行種子處理。

這通常是我們的代碼已經改變的指示,我需要運行單元測試來重新創建數據庫。除了我剛剛那樣做!我不相信我們的部署過程有什麼問題 - 測試服務器上的DLL似乎與我的本地環境中的版本相同。是否有任何其他設置或環境因素可能會導致有關模型自數據庫創建以來發生更改的錯誤?

我是新來的 - 謝謝你的幫助!

+1

您可以使用'System.Data.Entity.Infrastructure.EdmMetadata.TryGetModelHash(YourDbContext)'方法來獲取ModelHash並嘗試在您的本地PC和測試服務器上查看它們是否不同? – Marc

+0

在重新生成數據庫後,您是否運行了自定義工具以重新生成上下文或POCO? –

+1

@Marc是的哈希似乎是不同的。 – DaveBeta

回答

25

您看到的錯誤意味着存儲在EdmMetadata表中的模型哈希不同於從應用程序中的模型計算出的模型哈希。因爲您正在從不同的應用程序(您的開發應用程序)運行數據庫創建,所以這兩者可能會有所不同。這裏的簡單建議是:不要使用不同的應用程序來創建數據庫,而是讓主應用程序創建數據庫(自動或例如使用某個管理界面)。

正如你應該能夠通過消除負責這些檢查的慣例完全關閉此項檢查的另一種選擇:

modelBuilder.Conventions.Remove<IncludeMetadataConvention>(); 

型號哈希計算依賴於你的應用程序當前實體(任何簡單的修改結果不同的模型散列)和數據庫服務器版本/清單。例如,部署在SQL Server 2005和2008上的模型將具有不同的模型哈希(Express vs. Full或2008與2008 R2不應導致不同的模型哈希)。

+0

我們在桌面和服務器上有不同的操作系統版本,而且我們也有幾個不同版本的SQL Server,因爲我在本地使用SQL Express,但不在UAT上。如果僅僅是這些平臺差異會導致不同的'EdmMetadata'哈希值的生活事實,我很高興通過刪除約定來禁用哈希創建/檢查。謝謝! – DaveBeta

+0

'Warning 'System.Data.Entity.Infrastructure.IncludeMetadataConvention'已過時:'IncludeMetadataConvention不再使用。 EdmMetadata不包含在模型中。 現在用於檢測模型中的更改。' \t'** 2013 **答案在EF4中不再相關 – ppumkin

+0

@ppumkin:答案在EF4.3之前是相關的 –

2

實體框架代碼首先創建一個名爲EdmMetadata表。它保持你當前模型的散列。一旦你運行了應用程序,EF會檢查正在使用的模型是否與db'知道的模型相同。

如果要執行數據庫遷移,我建議你使用EF Code first migrations但它仍然是一個字母。

如果你不希望使用遷移,您可以:

手工處理模式的變化 - 這意味着所有的變化而移動EdmMetadata表來測試服務器的內容

設置分貝初始化到DropCreateDatabaseIfModelChanges(或更好的東西從它派生並使用種子()方法寫入初始數據)。要設置initialzer無論是在應用程序調用Database.SetInitializer()啓動或在使用AppSettings

<add key="DatabaseInitializerForType Fully.Qualified.Name.Of.Your.DbContext," value="Fully.Qualified.Name.Of.The.Initializer" /> 
+1

謝謝你。我的神祕之處在於,我有兩個應用程序服務器,據我所知它們是相同的 - 當然這些DLL是相同的,但它們似乎都認爲另一個創建的數據庫是「不同的」。我發現通過刪除EdmMetadata表,我可以抑制錯誤,並且這兩個應用程序似乎都能夠愉快地使用同一個數據庫。這看起來不對! – DaveBeta

+0

我在部署時有類似的問題,一個簡單的重新編譯和重新部署的DLL(絕對沒有變化),它修復了問題 – JarrettV

3

這可能幫助和鏈接斯科特摹博客將肯定是你的問題的解決方案檢查這個問題link

編輯1:這是link to Scott G blog

編輯2:您還可以檢查this如果集成服務器上首先使用數據庫

編輯3:這是一個more detailed answer像Scott G

+0

@與downvote的傢伙:你有沒有至少試圖檢查答案? –

9

由於不同平臺之間的反射排序差異,可能會發生這種情況。爲了驗證,您可以使用EdmxWriter API來比較兩種環境下的EDMX。如果任何表格有不同的列順序,那麼這是問題。

要解決此問題,您可以更改測試數據庫更新的方式,以便從測試服務器而不是本地盒更新測試數據庫。

我們將在下一個版本中解決這個問題。

+0

這也可能是基於構建配置的差異嗎?即調試vs發佈? – JarrettV

3

運行應用程序的兩臺服務器是否運行不同的操作系統(或Service Pack?)看起來SHA256CryptoService可能會拋出一個PlatformNotSupportedException,導致它返回到另一個方法。

http://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256cryptoserviceprovider.sha256cryptoserviceprovider.aspx

// System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace 
private static SHA256 GetSha256HashAlgorithm() 
{ 
    SHA256 result; 
    try 
    { 
    result = new SHA256CryptoServiceProvider(); 
    } 
    catch (PlatformNotSupportedException) 
    { 
    result = new SHA256Managed(); 
    } 
    return result; 
} 

您可能能夠通過使用反射來調用下面2(內部/私有)的每個服務器上的方法來進行測試。

MetaDataWorkspace.ToMetadataWorkspace(DbDatabaseMapping, Action<string>) 
CodeFirstCachedMetadataWorkspace.ComputeSha256Hash(string xml); 
+0

它回落到應該產生相同結果的託管版本。 – JarrettV

6

在代碼優先的方法中,SSDL是在執行代碼的過程中生成的。生成的SSDL中包含的信息之一是DbConnection中使用的提供程序的名稱。正如你所說,你連接到不同的數據庫引擎,所以你必須使用兩個不同的提供者。這完全改變了散列函數的輸出。

下面的代碼從裝配的EntityFramework提取:

using (XmlWriter writer = XmlWriter.Create(output, settings)) 
{ 
    new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer); 
} 
+0

我看到調試和發佈之間的差異,而不是來自提供者更改 – JarrettV

+0

儘管這不能回答我的問題,但它確實回答了原始問題。這是你的賞金。 – JarrettV

0

我只是偶然重命名我的.mdf文件,並得到這個錯誤。所以也請看這個。

相關問題