25

Tôi đang làm việc trên một dự án sử dụng Entity Framework 4.1 để duy trì các đối tượng khác nhau của chúng tôi cho cơ sở dữ liệu (mã đầu tiên).Entity Framework 4.1 Mô hình hỗ trợ ngữ cảnh đã thay đổi kể từ khi cơ sở dữ liệu được tạo, ngay sau khi tạo DB

Tôi đang thử nghiệm trong Visual Studio với một DB SQL Express cục bộ và máy chủ Jenkins của chúng tôi triển khai mã cam kết với máy chủ thử nghiệm. Khi điều này xảy ra, tôi tạm thời thay đổi chuỗi kết nối cục bộ của mình để trỏ tới máy chủ DB thử nghiệm và chạy thử nghiệm đơn vị để tạo lại cơ sở dữ liệu thử nghiệm sao cho phù hợp với các thực thể mới nhất của chúng tôi, v.v.

Gần đây tôi đã nhận thấy thử nghiệm của mình máy chủ đang đưa ra lỗi này:

Mô hình ủng hộ ngữ cảnh 'EntityFrameworkUnitOfWork' đã thay đổi kể từ khi cơ sở dữ liệu được tạo. Hoặc là tự xóa/cập nhật cơ sở dữ liệu, hoặc gọi Database.SetInitializer với một cá thể IDatabaseInitializer. Ví dụ, chiến lược DropCreateDatabaseIfModelChanges sẽ tự động xóa và tạo lại cơ sở dữ liệu, và tùy chọn tạo hạt giống với dữ liệu mới.

Điều này thường là dấu hiệu cho thấy mã của chúng tôi đã thay đổi và tôi cần chạy thử nghiệm đơn vị để tạo lại cơ sở dữ liệu. Ngoại trừ tôi đã làm điều đó! Tôi không tin rằng có bất cứ điều gì sai trái với quá trình triển khai của chúng tôi - các DLL trên máy chủ thử nghiệm dường như là các phiên bản giống như trong môi trường cục bộ của tôi. Có bất kỳ cài đặt hoặc yếu tố môi trường nào khác có thể gây ra lỗi này về mô hình đã thay đổi kể từ khi cơ sở dữ liệu được tạo không?

Tôi mới ở đây - cảm ơn bạn đã trợ giúp!

+1

Bạn có thể sử dụng phương thức 'System.Data.Entity.Infrastructure.EdmMetadata.TryGetModelHash (YourDbContext)' để lấy ModelHash và thử trên máy tính cục bộ của bạn và trình kiểm tra để xem chúng có khác không? – Marc

+0

Bạn có chạy công cụ tùy chỉnh để tạo lại ngữ cảnh hoặc POCO sau khi bạn tạo lại cơ sở dữ liệu không? –

+1

@Marc Có các băm dường như khác nhau. – DaveBeta

Trả lời

25

Lỗi bạn thấy có nghĩa là băm mẫu được lưu trữ trong EdmMetadata bảng khác với băm mô hình được tính toán từ mô hình trong ứng dụng.Bởi vì bạn đang chạy việc tạo cơ sở dữ liệu từ một ứng dụng khác (ứng dụng dev của bạn), có thể là hai ứng dụng đó khác nhau. Lời khuyên đơn giản ở đây là: không sử dụng các ứng dụng khác nhau để tạo cơ sở dữ liệu và thay vào đó hãy để ứng dụng chính của bạn tạo cơ sở dữ liệu (tự động hoặc ví dụ với một số giao diện quản trị).

Như một tùy chọn mà bạn sẽ có thể tắt việc kiểm tra này hoàn toàn bằng cách loại bỏ các quy ước chịu trách nhiệm về việc kiểm tra này:

modelBuilder.Conventions.Remove<IncludeMetadataConvention>(); 

Mẫu băm tính toán phụ thuộc vào thực thể hiện trong ứng dụng của bạn (bất kỳ kết quả thay đổi đơn giản trong băm mô hình khác nhau) và trên các phiên bản/tệp kê khai của máy chủ cơ sở dữ liệu. Ví dụ một mô hình được triển khai trên máy chủ SQL 2005 và 2008 sẽ có băm mô hình khác nhau (Express so với Full hoặc 2008 so với 2008 R2 không được dẫn đến băm mô hình khác nhau).

+0

Chúng tôi đã có một phiên bản hệ điều hành khác nhau trên máy tính để bàn và máy chủ, và chúng tôi cũng có một vài phiên bản khác nhau của SQL Server vì tôi đang sử dụng SQL Express cục bộ nhưng không phải trên UAT. Nếu nó chỉ là một thực tế của cuộc sống mà những khác biệt nền tảng sẽ gây ra một băm 'EdmMetadata' khác nhau, tôi hạnh phúc chỉ đơn giản là vô hiệu hóa việc tạo/kiểm tra băm bằng cách loại bỏ quy ước. Cảm ơn! – DaveBeta

+0

'Cảnh báo 'System.Data.Entity.Infrastructure.IncludeMetadataConvention' đã lỗi thời: 'IncludeMetadataConvention không còn được sử dụng nữa. EdmMetadata không được bao gồm trong mô hình. hiện được sử dụng để phát hiện các thay đổi trong mô hình. ' \t '** 2013 ** Câu trả lời không còn liên quan trong EF4 – ppumkin

+0

@ppumkin: Trả lời có liên quan trước EF4.3 –

2

Mã khung thực thể trước tiên tạo một bảng có tên là EdmMetadata. Nó giữ một băm của mô hình hiện tại của bạn. Khi bạn chạy ứng dụng EF kiểm tra xem mô hình được sử dụng có giống với mô hình mà db 'biết về' hay không.

Nếu bạn muốn thực hiện di chuyển cơ sở dữ liệu, tôi khuyên bạn nên sử dụng EF Code first migrations mặc dù nó vẫn là alpha.

Nếu bạn không muốn sử dụng di chuyển nào bạn có thể:

xử lý sự thay đổi schema bằng tay - có nghĩa là di chuyển các nội dung của bảng EdmMetadata đến máy chủ thử nghiệm cùng với tất cả những thay đổi

hoặc

đặt trình khởi tạo db thành DropCreateDatabaseIfModelChanges (hoặc một cái gì đó tốt hơn bắt nguồn từ nó và sử dụng phương thức Seed() để ghi dữ liệu ban đầu). Để thiết lập các initialzer hoặc gọi Database.SetInitializer() trên ứng dụng bắt đầu hoặc sử dụng appSettings

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

Cảm ơn vì điều đó. Bí ẩn của tôi là nhiều hơn xung quanh thực tế là tôi có 2 máy chủ ứng dụng mà theo như tôi có thể nói là giống hệt nhau - chắc chắn các DLL là giống nhau, và cả hai dường như nghĩ rằng DB tạo bởi khác là "khác nhau". Tôi đã tìm thấy rằng chỉ bằng cách xóa bảng EdmMetadata tôi có thể ngăn chặn lỗi và cả hai ứng dụng dường như đang làm việc với cùng một cơ sở dữ liệu vui vẻ. Điều này có vẻ sai! – DaveBeta

+0

Tôi đang gặp vấn đề tương tự tại thời điểm triển khai, biên dịch lại và triển khai lại đơn giản của dll (hoàn toàn không có thay đổi) và sửa lỗi vấn đề – JarrettV

3

Điều này có thể giúp đỡ và liên kết để Scott G blog sẽ chắc chắn là một giải pháp cho vấn đề của bạn kiểm tra câu hỏi này link

Sửa 1: đây là link to Scott G blog

chỉnh sửa 2: bạn cũng có thể kiểm tra this nếu bạn sử dụng một cơ sở dữ liệu đầu tiên trên máy chủ tích hợp

Sửa 3: Đây là một more detailed answer giống như một từ Scott G

+0

@ Người có giới hạn: Bạn ít nhất đã cố gắng kiểm tra câu trả lời? –

9

Điều này có thể xảy ra do sự khác biệt về thứ tự phản ánh trên các nền tảng khác nhau. Để xác minh, bạn có thể sử dụng API EdmxWriter để so sánh EDMX từ cả hai môi trường. Nếu bất kỳ bảng nào có thứ tự cột khác nhau thì đây là vấn đề.

Để giải quyết sự cố, bạn có thể thay đổi cách cơ sở dữ liệu thử nghiệm của bạn được cập nhật sao cho cơ sở dữ liệu thử nghiệm được cập nhật từ máy chủ thử nghiệm thay vì hộp địa phương của bạn.

Chúng tôi sẽ khắc phục sự cố này trong bản phát hành tiếp theo.

+0

Đây có phải là sự khác biệt cũng dựa trên cấu hình xây dựng không? tức là gỡ lỗi vs phát hành? – JarrettV

3

Hai máy chủ đang chạy ứng dụng của bạn đang chạy các hệ điều hành khác nhau (hoặc các gói dịch vụ?) Có vẻ như SHA256CryptoService đã sử dụng có thể ném một PlatformNotSupportedException khiến nó trở thành phương thức khác.

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; 
} 

Bạn có thể kiểm tra điều này bằng cách sử dụng phản ánh để gọi 2 (private/nội bộ) phương pháp sau đây trên mỗi máy chủ.

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

Nó rơi trở lại phiên bản được quản lý sẽ tạo ra kết quả tương tự. – JarrettV

6

Trong phương pháp tiếp cận mã đầu tiên, SSDL được tạo trong khi thực thi mã. Một trong những thông tin có trong SSDL được tạo ra là tên của nhà cung cấp được sử dụng trong DbConnection. Như bạn đã nói, bạn đang kết nối với các cơ sở dữ liệu khác nhau, vì vậy bạn phải sử dụng hai nhà cung cấp khác nhau. Điều này hoàn toàn thay đổi đầu ra của hàm băm.

Mã dưới đây được chiết xuất từ ​​lắp ráp EntityFramework:

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

Tôi thấy sự khác biệt giữa gỡ lỗi và phát hành, không phải từ nhà cung cấp thay đổi – JarrettV

+0

Mặc dù điều này không trả lời câu hỏi của tôi, nó trả lời câu hỏi gốc. Đây là tiền thưởng của bạn. – JarrettV

0

tôi chỉ vô tình đổi tên file MDF của tôi và đã nhận lỗi này. Vì vậy, nhìn cũng cho điều này.

Các vấn đề liên quan