Je travaille sur un projet qui utilise Entity Framework 4.1 pour conserver nos différents objets dans la base de données (code en premier).
Je teste dans Visual Studio avec une base de données SQL Express locale et notre serveur Jenkins déploie le code validé sur un serveur de test. Lorsque cela se produit, je modifie temporairement ma chaîne de connexion locale pour qu'elle pointe vers le serveur de base de données en test et exécute un test unitaire pour recréer la base de données de test afin qu'elle corresponde à nos dernières entités, etc.
J'ai récemment remarqué que notre serveur de test donnait cette erreur:
Le modèle sauvegardant le contexte 'EntityFrameworkUnitOfWork' a changé depuis la création de la base de données. Supprimez/mettez à jour manuellement la base de données ou appelez Database.SetInitializer avec une instance IDatabaseInitializer. Par exemple, la stratégie DropCreateDatabaseIfModelChanges supprimera et recréera automatiquement la base de données et, éventuellement, l'ensemencera avec de nouvelles données.
Cela indique généralement que notre code a changé et que je dois exécuter le test unitaire pour recréer la base de données. Sauf que je viens de faire ça! Je ne crois pas que notre processus de déploiement présente un problème: les DLL sur le serveur de test semblent être les mêmes versions que dans mon environnement local. Existe-t-il d'autres paramètres ou facteurs d'environnement pouvant entraîner cette erreur lorsque le modèle a été modifié depuis la création de la base de données?
Je suis nouveau ici - merci pour toute aide!
L'erreur que vous voyez signifie que le hachage du modèle stocké dans la table EdmMetadata
est différent du hachage du modèle calculé à partir du modèle de l'application. Étant donné que vous exécutez la création d'une base de données à partir d'une application différente (votre application de développement), il est possible que ces deux applications soient différentes. Voici un conseil simple: n'utilisez pas différentes applications pour créer une base de données, mais laissez plutôt votre application principale créer la base de données (automatiquement ou avec une interface d'administration par exemple).
Une autre option consiste à désactiver complètement cette vérification en supprimant la convention responsable de ces vérifications:
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
Le calcul du modèle de hachage dépend des entités actuelles de votre application (toute modification simple entraîne un hachage de modèle différent) et des versions/manifestes du serveur de base de données. Par exemple, un modèle déployé sur SQL Server 2005 et 2008 aura un hachage de modèle différent (Express par rapport à Full ou 2008 par rapport à 2008 R2 ne devrait pas donner lieu à un hachage de modèle différent).
Cela peut se produire en raison des différences d’ordre de réflexion entre différentes plates-formes. Pour vérifier, vous pouvez utiliser l'API EdmxWriter pour comparer EDMX des deux environnements. Si l’un des tableaux a un ordre de colonne différent, c’est le problème qui se pose.
Pour contourner le problème, vous pouvez modifier la façon dont votre base de données de test est mise à jour pour qu'elle soit mise à jour à partir de votre serveur de test plutôt que de votre boîte locale.
Nous allons résoudre ce problème dans la prochaine version.
Dans l'approche code-first, la SSDL est générée lors de l'exécution du code. Une des informations incluses dans la SSDL générée est le nom du fournisseur utilisé dans DbConnection. Comme vous l'avez dit, vous vous connectez à différents moteurs de bases de données, vous devez donc utiliser deux fournisseurs différents. Ceci change complètement la sortie de la fonction de hachage.
Le code ci-dessous a été extrait de l'assembly EntityFramework:
using (XmlWriter writer = XmlWriter.Create(output, settings))
{
new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer);
}
Cela pourrait aider et le lien vers Scott G blog sera certainement une solution à votre problème vérifier cette question link
Edit 1: c'est le lien vers le blog de Scott G
Edit 2: Vous pouvez également vérifier this si vous utilisez d'abord une base de données sur le serveur d'intégration
Edit 3: Ceci est une réponse plus détaillée comme celle de Scott G
Les deux serveurs exécutant votre application exécutent-ils des systèmes d'exploitation (ou des service packs?) Différents. Il semble que le SHA256CryptoService utilisé peut émettre une exception PlatformNotSupportedException, ce qui provoque le recours à une autre méthode.
// System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace
private static SHA256 GetSha256HashAlgorithm()
{
SHA256 result;
try
{
result = new SHA256CryptoServiceProvider();
}
catch (PlatformNotSupportedException)
{
result = new SHA256Managed();
}
return result;
}
Vous pourrez peut-être tester cela en utilisant la réflexion pour appeler les 2 méthodes suivantes (internes/privées) sur chaque serveur.
MetaDataWorkspace.ToMetadataWorkspace(DbDatabaseMapping, Action<string>)
CodeFirstCachedMetadataWorkspace.ComputeSha256Hash(string xml);
Le code Entity Framework crée d'abord une table appelée EdmMetadata. Il garde un hachage de votre modèle actuel. Une fois que vous avez exécuté l'application, EF vérifie si le modèle utilisé est identique à celui que la base de données connaît.
Si vous souhaitez effectuer une migration de base de données, je vous suggère d'utiliser Premières migrations de code EF bien que ce soit toujours un alpha.
Si vous ne souhaitez pas utiliser les migrations, vous pouvez soit:
gérer le changement de schéma manuellement - cela signifie déplacer le contenu de la table EdmMetadata sur le serveur de test avec toutes les modifications
ou
définissez l'initialiseur de base de données sur DropCreateDatabaseIfModelChanges (ou un dérivé de celui-ci, et utilisez la méthode Seed () pour écrire les données initiales). Pour définir initialzer, appelez Database.SetInitializer () au démarrage de l'application ou utilisez la commande appSettings.
<add key="DatabaseInitializerForType Fully.Qualified.Name.Of.Your.DbContext," value="Fully.Qualified.Name.Of.The.Initializer" />
J'ai accidentellement renommé mon fichier .mdf et j'ai eu cette erreur. Alors cherchez aussi cela.