Entity Framework 4.1 Модель, що підтримує контекст, змінилася з моменту створення бази даних відразу після створення БД

Я працюю над проектом, який використовує Entity Framework 4.1 для збереження наших різних об'єктів до бази даних (спочатку код).

Я тестую в Visual Studio за допомогою локальної SQL Express DB, і наш сервер Jenkins розгортає виконуваний код на сервері тестування. Коли це станеться, я тимчасово зміню мій локальний рядок з'єднання, щоб вказати на сервер тестування DB, і запустити тестування на об'єкт, щоб відновити тестову базу даних, щоб вона відповідала нашим останнім об'єктам тощо.

Нещодавно я помітив, що наш тестовий сервер надає цю помилку:

Модель зміни контексту EntityFrameworkUnitOfWork змінилася з моменту створення бази даних. Вживати або видалити/оновити базу даних вручну, або викликати Database.SetInitializer з екземпляром IDatabaseInitializer. Наприклад, стратегія DropCreateDatabaseIfModelChanges автоматично видаляє та відтворює базу даних та, можливо, набирає її з новими даними.

Це, як правило, означає, що наш код змінився, і мені потрібно запустити тестування для повторного створення бази даних. Крім того, я просто зробив це! Я не вірю, що в нашому процесі розгортання є щось погане - DLL на тестовому сервері виглядає так само, як і в моєму локальному середовищі. Чи існують інші параметри або фактори середовища, які можуть спричинити цю помилку щодо зміни моделі після створення бази даних?

Я тут новий - спасибі за будь-яку допомогу!

25
Не могли б ви використати метод System.Data.Entity.Infrastructure.EdmMetadata.TryGetModelHas & html; (YourDbContext) , щоб отримати ModelHash і спробувати це на локальному комп'ютері та сервері перевірки, щоб побачити, чи вони різні?
додано Автор Marc, джерело
Ви запустили спеціальний інструмент для відновлення контексту або POCO після того, як ви відновили базу даних?
додано Автор radu florescu, джерело
@Marc Так хеші, здається, різні.
додано Автор DaveBeta, джерело
@ Floradu88 Не 100% впевнений, що ви маєте на увазі. Я використовував Database.SetInitializer з DropCreateDatabaseAlways DBContext для відновлення DB. Я думаю, це буде POCO?
додано Автор DaveBeta, джерело

7 Відповіді

Помилка, яку ви бачите, означає, що хеш моделі, збереженої в таблиці EdmMetadata </​​code>, відрізняється від моделі хешу, обчисленого за моделлю у програмі. Оскільки ви створюєте створення бази даних з іншої програми (вашої додаткової програми), ці два варіанти можуть бути різними. Проста порада тут: не використовуйте різні програми для створення бази даних, а замість того, щоб ваш головний додаток створював базу даних (автоматично або, наприклад, з деяким інтерфейсом адміністратора).

Як ще один варіант, ви можете повністю вимкнути цю перевірку, видаливши конвенцію, відповідальну за ці перевірки:

modelBuilder.Conventions.Remove();

Обчислення хеш-моделей залежить від поточних об'єктів у вашій програмі (будь-які прості результати зміни в різних хеш-моделях) та версії/маніфест сервера баз даних. Наприклад, модель, розгорнута на сервері SQL 2005 і 2008, матиме різні моделі хешу (Express vs. Full або 2008 проти 2008 R2 не повинно призвести до різного хешу моделі).

25
додано
@ppumkin: відповідь була актуальною до EF4.3
додано Автор Ladislav Mrnka, джерело
Попередження 2 'System.Data.Entity.Infrastructure.IncludeMetadata & amp; zwnj; конвенція' застаріла: 'The IncludeMetadataConvention більше не використовується. EdmMetadata не включено до моделі. <�див. cref = "EdmModelDiffer" /> тепер використовується для виявлення змін у моделі. ' 2013 Відповідь більше не відповідає EF4
додано Автор ppumkin, джерело
Хто-небудь отримав оновлення для перших сценаріїв EF5.0 або Database/Model? (подібне до цього питання stackoverflow.com/questions/16459047/ … )
додано Автор Dave A-W, джерело
У нас є інша версія ОС на робочому столі та на сервері, і у нас також є кілька різних версій SQL Server, тому що я використовую SQL Express локально, але не на UAT. Якщо це просто факт життя, що ці розбіжності на платформі викликають інший хеш EdmMetadata </​​code>, я радий просто відключити створення/перевірку хешу, видаливши конвенцію. Дякую!
додано Автор DaveBeta, джерело

Це може трапитися з-за відмінностей упорядкування порядку між різними платформами. Щоб перевірити, ви можете використовувати API EdmxWriter для порівняння EDMX з обох середовищ. Якщо в будь-якому з таблиць використовується інший набір стовпчиків, це проблема.

Щоб вирішити проблему, ви можете змінити спосіб, у який тестова база даних оновлюється, так що вона оновлюється з вашого тестового сервера, а не вашого місцевого вікна.

Ми вирішимо цю проблему в наступному випуску.

9
додано
Чи може це бути різницею також на основі конфігурації збірки? тобто налагодження проти релізу?
додано Автор JarrettV, джерело

У підході коду, SSDL створюється під час виконання коду. Однією з інформації, що входить до складеного SSDL, є ім'я провайдера, що використовується в DbConnection. Як ви сказали, ви підключаєтеся до різних движків баз даних, так що ви повинні використовувати два різних постачальника. Це повністю змінює вихідну функцію хешування.

Нижче коду було вилучено з монтажу EntityFramework:

using (XmlWriter writer = XmlWriter.Create(output, settings))
{
    new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer);
}
6
додано
Я бачу різницю між налагодженням та випуском, а не зміною провайдера
додано Автор JarrettV, джерело
Хоча це не відповідає на моє запитання, він відповідає на початкове питання. Ось ваша щедрость.
додано Автор JarrettV, джерело

This might help and the link to Scott G blog will sure be a solution to your problem check this question link

Edit 1: this is the link to Scott G blog

Редагувати 2: ви також можете перевірити цей , якщо ви вперше використовуєте базу даних на сервері інтеграції

Редагувати 3: це більше докладна відповідь , подібна до одного з Скотта Г.

3
додано
@ Хлопець зі знижкою: Ви хоча б спробували перевірити відповіді?
додано Автор radu florescu, джерело

Чи використовують два сервери, що працюють із вашою програмою, різні операційні системи (або пакети оновлень?). Схоже, що використовується 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)
CodeFirstCachedMetadataWorkspace.ComputeSha256Hash(string xml);
3
додано
Він повертається до керованої версії, яка повинна зробити такий самий результат.
додано Автор JarrettV, джерело

Код Entity Framewабоk спочатку створює таблицю з ім'ям EdmMetadata. Він зберігає хеш поточної моделі. Після запуску програми EF перевіряє, чи використовувана модель є такою самою, як модель, про яку дБ "знає про".

If you want to perfабоm database migration, I suggest you use EF Code first migrations though it's still an alpha.

If you don't want to use migrations you can either:

handle the schema change manually - that means moving the content of the EdmMetadata table to the test server along with all the changes

або

set the db initializer to DropCreateDatabaseIfModelChanges (або better something derived from it and use the Seed() method to write the initial data). To set the initialzer either call Database.SetInitializer() on application start або use the appSettings


2
додано
у мене є однакова проблема при розгортанні часу, проста перекомпіляція та перерозподіл DLL (абсолютно ніяких змін), і це виправляє проблему
додано Автор JarrettV, джерело
Дякую за це. Моя таємниця полягала в тому, що у мене є 2 сервери додатків, які, наскільки я можу сказати, ідентичні - звичайно, DLL ідентичні, і тим не менше, вони обидва, здається, думають, що БД, створене іншим, є "іншим". Я виявив, що просто видаляючи таблицю EdmMetadata я можу придушити помилку, і обидва програми, здається, працюють з тією ж базою даних щасливо. Це здається неправильним!
додано Автор DaveBeta, джерело

Я випадково перейменував файл .mdf і отримав цю помилку. Тож подивіться і на це.

0
додано
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug