Il existe déjà un objet nommé dans la base de données
Mise à jour-échec de la base de données depuis la Console du Gestionnaire de paquets. J'ai utilisé Entity Framework 6.X et Code-première approche. L'erreur est
"Il y a déjà un objet nommé 'AboutUs' dans la base de données."
Comment puis-je résoudre ce problème?
internal sealed class Configuration
: DbMigrationsConfiguration<Jahan.Blog.Web.Mvc.Models.JahanBlogDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = false;
}
protected override void Seed(Jahan.Blog.Web.Mvc.Models.JahanBlogDbContext context)
{
}
}
Mon DbContext est:
public class JahanBlogDbContext : IdentityDbContext<User, Role, int, UserLogin, UserRole, UserClaim>
{
public JahanBlogDbContext()
: base("name=JahanBlogDbConnectionString")
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<JahanBlogDbContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Comment>().HasRequired(t => t.Article).WithMany(t => t.Comments).HasForeignKey(d => d.ArticleId).WillCascadeOnDelete(true);
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().ToTable("User");
modelBuilder.Entity<Role>().ToTable("Role");
modelBuilder.Entity<UserRole>().ToTable("UserRole");
modelBuilder.Entity<UserLogin>().ToTable("UserLogin");
modelBuilder.Entity<UserClaim>().ToTable("UserClaim");
}
public virtual DbSet<Article> Articles { get; set; }
public virtual DbSet<ArticleLike> ArticleLikes { get; set; }
public virtual DbSet<ArticleTag> ArticleTags { get; set; }
public virtual DbSet<AttachmentFile> AttachmentFiles { get; set; }
public virtual DbSet<Comment> Comments { get; set; }
public virtual DbSet<CommentLike> CommentLikes { get; set; }
public virtual DbSet<CommentReply> CommentReplies { get; set; }
public virtual DbSet<ContactUs> ContactUs { get; set; }
public virtual DbSet<Project> Projects { get; set; }
public virtual DbSet<ProjectState> ProjectStates { get; set; }
public virtual DbSet<ProjectTag> ProjectTags { get; set; }
public virtual DbSet<Rating> Ratings { get; set; }
public virtual DbSet<Tag> Tags { get; set; }
public virtual DbSet<AboutUs> AboutUs { get; set; }
}
Console De Gestion Des Paquets:
PM> update-database -verbose -force
Using StartUp project 'Jahan.Blog.Web.Mvc'.
Using NuGet project 'Jahan.Blog.Web.Mvc'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'Jahan-Blog' (DataSource: (local), Provider: System.Data.SqlClient, Origin: Configuration).
No pending explicit migrations.
Applying automatic migration: 201410101740197_AutomaticMigration.
CREATE TABLE [dbo].[AboutUs] (
[Id] [int] NOT NULL IDENTITY,
[Description] [nvarchar](max),
[IsActive] [bit] NOT NULL,
[CreatedDate] [datetime],
[ModifiedDate] [datetime],
CONSTRAINT [PK_dbo.AboutUs] PRIMARY KEY ([Id])
)
System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'AboutUs' in the database.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext`1 c)
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)
at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery()
at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext)
at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext)
at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection)
at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClass30.<ExecuteStatements>b__2e()
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0()
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation)
at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements, DbTransaction existingTransaction)
at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, IEnumerable`1 systemOperations, Boolean downgrading, Boolean auto)
at System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, VersionedModel sourceModel, VersionedModel targetModel, Boolean downgrading)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.AutoMigrate(String migrationId, VersionedModel sourceModel, VersionedModel targetModel, Boolean downgrading)
at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
ClientConnectionId:88b66414-8776-45cd-a211-e81b2711c94b
There is already an object named 'AboutUs' in the database.
PM>
11 réponses
Il semble qu'il y ait un problème dans le processus de migration, exécutez la commande add-migration dans "console du Gestionnaire de paquets":
Ajouter-Migration Initiale-IgnoreChanges
Effectuez quelques modifications, puis mettez à jour la base de données à partir du fichier "Initial":
Mise à Jour de la Base de données -verbose
Modifier: - IgnoreChanges est dans EF6 mais pas dans EF Core, voici une solution de contournement: https://stackoverflow.com/a/43687656/495455
Peut-être avez-vous changé l'espace de noms dans votre projet!
Il y a une table dans votre base de données appelée dbo.__MigrationHistory
. La table a une colonne appelée ContextKey
.
La valeur de cette colonne est basée sur votre namespace
. par exemple, est "DataAccess.Migrations.Configuration
".
lorsque vous modifiez l'espace de noms, il provoque des noms de table en double avec des espaces de noms différents.
Donc, après avoir changé l'espace de noms du côté code, modifiez également l'espace de noms de cette table dans la base de données (pour tous rangée).
Par exemple, si vous changez l'espace de noms en EFDataAccess
, vous devez changer les valeurs de la colonne ContextKey
dans dbo.__MigrationHistory
en "EFDataAccess.Migrations.Configuration
".
Puis dans le code côté, dans Outils => Gestionnaire de paquets de la Console, utilisez la update-database
commande.
Une autre option au lieu de changer la valeur de contexte dans la base de données est de coder en dur la valeur de contexte dans votre code à l'ancienne valeur d'espace de noms. Ceci est possible en héritant de DbMigrationsConfiguration<YourDbContext>
et dans le constructeur, il suffit d'attribuer l'ancienne valeur de contexte à ContextKey
, que hériter de MigrateDatabaseToLatestVersion<YourDbContext, YourDbMigrationConfiguration>
et laisser cette classe vide. La dernière chose à faire est d'appeler Database.SetInitializer(new YourDbInitializer());
dans votre DbContext dans un constructeur statique.
J'espère que votre problème sera résolu.
"Il y a déjà un objet nommé 'AboutUs' dans la base de données."
Cette exception vous indique que quelqu'un a déjà ajouté un objet nommé 'AboutUs' à la base de données.
AutomaticMigrationsEnabled = true;
peut y conduire puisque les versions de base de données ne sont pas contrôlées par vous dans ce cas. Afin d'éviter les migrations imprévisibles et de s'assurer que chaque développeur de l'équipe travaille avec la même structure de base de données , je vous suggère de définir AutomaticMigrationsEnabled = false;
.
Migrations automatiques et Les migrations codées peuvent vivre à côté si vous êtes très prudent et le seul développeur sur un projet.
Il y a une citation de code automatique premières migrations post sur Data Developer Center :
Les Migrations automatiques vous permettent d'utiliser les premières Migrations de Code sans avoir un fichier de code dans votre projet pour chaque modification que vous apportez. Pas tous les modifications peuvent être appliquées automatiquement - par exemple les renommages de colonne exiger l'utilisation d'une migration basée sur le code.
Recommandation pour les environnements D'équipe
Vous pouvez intercaler les migrations automatiques et basées sur le code, mais c'est non recommandé dans les scénarios de développement d'équipe. Si vous faites partie d'un équipe de développeurs qui utilisent le contrôle de source vous devez soit utiliser migrations purement automatiques ou migrations purement basées sur le code. Compte tenu de la limitations des migrations automatiques nous vous recommandons d'utiliser des migrations dans les environnements d'équipe.
Dans mon cas, ma table EFMigrationsHistory
a été vidée (d'une manière ou d'une autre) et en essayant d'exécuter update-database
, j'obtiendrais:
Il existe déjà un objet nommé 'AspNetUsers' dans la base de données
Après avoir vu que la table avait été vidée, il était logique qu'elle essayait de réexécuter la migration initiale et d'essayer de recréer les tables.
Pour résoudre ce problème, j'ai ajouté des lignes dans ma table EFMigrationsHistory
. 1 ligne pour chaque migration avec laquelle je savais que la base de données était à jour.
Une ligne aura 2 colonnes: MigrationId
et ProductVersion
MigrationId
est le nom de votre fichier de migration. Exemple: 20170628112345_Initial
ProductVersion
est la version ef que vous utilisez. Vous pouvez le trouver en tapant Get-Package
dans la Console du Gestionnaire de paquets et en recherchant votre paquet ef.
J'espère que cela est utile pour quelqu'un.
Assurez-vous que votre projet de démarrage de solutions a la bonne connectionstring dans le fichier de configuration. Ou définissez le paramètre-StartUpProjectName lors de l'exécution de la commande update-database. Le paramètre-StartUpProjectName spécifie le fichier de configuration à utiliser pour les chaînes de connexion nommées. S'il est omis, le fichier de configuration du projet spécifié est utilisé.
Voici un lien pour les références de commande ef-migration http://coding.abel.nu/2012/03/ef-migrations-command-reference/
Dans mon cas, j'avais renommé l'assembly qui contenait le modèle entity framework code-first. Bien que le schéma réel n'ait pas changé du tout, la table migrations appelée
dbo.__MigrationHistory
Contient une liste des migrations déjà effectuées basée sur l'ancien nom d'assembly . J'ai mis à jour l'ancien nom dans la table migrations pour correspondre au nouveau et la migration a ensuite fonctionné à nouveau.
Supprimez les lignes de la table dbo_MigrationHistory ou supprimez la table et exécutez
update-database -verbose
Il exécutera toutes les migrations de votre projet une par une
Note: solution non recommandée. mais la correction rapide dans certains cas.
Pour moi, dbo._MigrationHistory
dans la base de données de production a manqué les enregistrements de migration pendant le processus de publication, mais la base de données de développement avait tous les enregistrements de migration.
Si vous êtes sûr que la base de données de production a le même schéma et le plus récent par rapport à la base de données de développement, copier tous les enregistrements de migration dans la base de données de production peut résoudre le problème.
Vous pouvez le faire uniquement dans VisualStudio.
- ouvrez le panneau' SQL Server Object Explorer ' > cliquez avec le bouton droit de la souris
dbo._MigrationHistory
table dans la base de données source(dans mon cas dev db) > cliquez sur " comparaison de données..."du menu. - ensuite, l'assistant de comparaison de données apparaît, sélectionnez la base de données cible (dans mon cas, la base de données de production) et cliquez sur Suivant.
- quelques secondes plus tard, il affichera certains enregistrements uniquement dans la base de données source. cliquez simplement sur le bouton "Mettre à jour la cible".
- dans le navigateur, appuyez sur le bouton Actualiser et voir le message d'erreur disparu.
Notez que, encore une fois, il n'est pas recommandé dans un projet complexe et sérieux. Utilisez ceci seulement vous avez un problème pendant ASP.Net ou EntityFramework learning.
Dans mon cas, le problème était dans Seeder. J'ai été appeler _ctx.La base de données.EnsureCreated() à l'intérieur de celui-ci et pour autant que j'ai compris, la commande update database a été exécutée avec succès, mais seeder a essayé de créer la base de données "deuxième" fois.
Comment s'adresser:
- Faites la mise à jour de l'écrou, démarrez simplement l'application et appelez EnsureCreated (). La base de données sera créée / mise à jour
- commentez ou supprimez le semoir.
Exécutez simplement la commande update-migration-Script. Cette générer de nouvelles *.script sql qui inclut toutes les modifications de base de données incluses dans la migration. À la fin du code sont insert commandes quelque chose comme ceci: INSERT [dbo].[__MigrationHistory] ([MigrationId], [ContextKey], [Model], [ProductVersion]) vous pouvez simplement exécuter tout cet INSERT et la base de données sera synchronisée
Dans le fichier de migration, vérifiez la méthode Public override void Up () . Peut-être que vous essayez de créer un nouvel objet db qui est déjà dans la base de données. Donc, vous devez supprimer cet objet / table avant la création de l'objet db. Il suffit de faire comme ci-dessous -
DropTable("dbo.ABC");
CreateTable(
"dbo.ABC",
c => new
{
Id = c.Int(nullable: false, identity: true),
..
}
Et maintenant exécutez votre migration
Update-Database -TargetMigration: "2016_YourMigration"