Я работаю над проектом, который использует Entity Framework 4.1 для сохранения наших различных объектов в базе данных (сначала код).
Я тестирую в Visual Studio с локальной базой данных SQL Express, и наш сервер Jenkins развертывает зафиксированный код на тестовом сервере. Когда это происходит, я временно изменяю свою локальную строку подключения, чтобы указать на сервер тестовой БД, и запускаю модульный тест, чтобы воссоздать тестовую базу данных, чтобы она соответствовала нашим последним объектам и т. Д.
Недавно я заметил, что наш тестовый сервер выдает следующую ошибку:
Модель, поддерживающая контекст EntityFrameworkUnitOfWork, изменилась с момента создания базы данных. Либо вручную удалите / обновите базу данных, либо вызовите Database.SetInitializer с экземпляром IDatabaseInitializer. Например, стратегия DropCreateDatabaseIfModelChanges автоматически удалит и воссоздает базу данных, а также при необходимости заполнит ее новыми данными.
Обычно это указывает на то, что наш код изменился, и мне нужно запустить модульный тест, чтобы воссоздать базу данных. Вот только я только что это сделал! Я не верю, что с нашим процессом развертывания что-то не так - библиотеки DLL на тестовом сервере кажутся теми же версиями, что и в моей локальной среде. Существуют ли какие-либо другие настройки или факторы среды, которые могут вызвать эту ошибку о том, что модель изменилась с момента создания базы данных?
Я здесь новичок - спасибо за любую помощь!
Ошибка, которую вы видите, означает, что хеш модели, сохраненный в таблице EdmMetadata
, отличается от хеша модели, вычисленного из модели в приложении. Поскольку вы запускаете создание базы данных из другого приложения (вашего разработчика), возможно, что эти два отличаются. Вот простой совет: не используйте разные приложения для создания базы данных, а вместо этого позвольте основному приложению создать базу данных (автоматически или, например, с некоторым интерфейсом администратора).
В качестве другого варианта вы сможете полностью отключить эту проверку, удалив соглашение, ответственное за эти проверки:
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
Вычисление хеш-модели модели зависит от текущих объектов в вашем приложении простой результат изменения в хэше другой модели) и в версиях / манифестах сервера базы данных. Например, модель, развернутая на SQL Server 2005 и 2008, будет иметь разный хеш модели (Express против Full или 2008 против 2008 R2 не должен приводить к разным хэшам модели).
В подходе «сначала код» SSDL генерируется во время выполнения кода. Одной из сведений, включенных в сгенерированный SSDL, является имя провайдера, используемого в DbConnection. Как вы сказали, вы подключаетесь к разным ядрам баз данных, поэтому вы должны использовать двух разных провайдеров. Это полностью меняет выходные данные функции хеширования.
Следующий код был извлечен из сборки EntityFramework:
using (XmlWriter writer = XmlWriter.Create(output, settings))
{
new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer);
}
Являются ли два сервера, на которых запущено ваше приложение, под управлением разных операционных систем (или пакетов обновления?) Похоже, что используемый SHA256CryptoService может вызвать исключение PlatformNotSupportedException, которое вызывает его откат к другому методу.
// 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);