web-dev-qa-db-fra.com

Entity Framework L'instruction ALTER TABLE a été en conflit avec la contrainte FOREIGN KEY.

Lors de la mise à jour de la base de données dans Entity Framework, code d'abord Migration, le message d'erreur suivant s'affiche:

L'instruction ALTER TABLE est en conflit avec la contrainte FOREIGN KEY "FK_dbo.Clients_dbo.MedicalGroups_MedicalGroupId". Le conflit s'est produit dans la base de données "hrbc", table "dbo.MedicalGroups", colonne "Id".

Ceci est ma classe:

public partial class Client
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? MedicalGroupId { get; set; }
    [ForeignKey("MedicalGroupId")]
    public virtual MedicalGroups MedicalGroup { get { return _MedicalGroup; } set { _MedicalGroup = value; } }
}

Voici ma 2e classe:

public partial class MedicalGroups
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

Et voici ma migration que j'essaie d'appliquer:

public override void Up()
{
    AddForeignKey("dbo.Clients", "MedicalGroupId", "dbo.MedicalGroups", "Id");
    CreateIndex("dbo.Clients", "MedicalGroupId");
}
48
Zaid Iqbal

J'ai la solution de mon problème. Le problème est "données" que j'ai dans ma table des clients. Parce que ma table client a des valeurs medicalgroupid qui n'existent pas, c'est pourquoi elle me donne une erreur sur la contrainte de clé étrangère.

Update Client set MedicalGroupId = NULL
2
Zaid Iqbal

Vérifiez qu'il n'y a pas de données existantes dans la base de données en conflit avec la contrainte FK entraînant l'échec de la création.

90
Turnkey

Je pense que @Cory vous approchait de la bonne solution, vous n’avez tout simplement pas pris le temps d’enquêter.

Dans le code add-migration, la migration a probablement généré

public override void Up()
{
AddColumn("dbo.ClientContacts", "FamilialRelationshipId", c => c.Int(nullable: false));
CreateIndex("dbo.ClientContacts", "FamilialRelationshipId");
AddForeignKey("dbo.ClientContacts", "FamilialRelationshipId", "dbo.FamilialRelationships",        "FamilialRelationshipId");
}

Notice nullable: false; Si votre modèle avait un identifiant d'int au lieu d'int? (nullable int) le code de migration définira nullable sur false . Votre modèle indique que vous utilisez un int non nullable dont la valeur par défaut est 0 et que vous n'avez probablement pas d'élément de clé étrangère avec une valeur de 0. 

Maintenant, vous devrez soit créer une valeur par défaut, qui existe dans la table de clé étrangère, .__, soit créer la contrainte sans vérification si vous utilisez SQL Server pour créer la contrainte. Rappelez-vous cependant que si vous décorez votre propriété avec un attribut [DefaultValue (0)], cela ne modifiera pas les données existantes, comme le ferait une colonne SQL Ajouter, si une valeur par défaut était spécifiée.

Je vous recommande de modifier votre classe de modèle pour autoriser un int nullable. Ensuite, dans votre méthode de départ, créez une méthode simple contre dbcontext pour mettre à jour la nouvelle colonne avec une valeur par défaut, car l'attribut [DefaultValue] dans les annotations de données ne modifiera pas vos données.

Add-Migration/Update-Database pour créer la colonne et la contrainte . Ensuite, modifiez votre modèle si vous souhaitez autoriser un int non nullable, et en supposant que vous modifiez toutes les lignes en une valeur valide pour la clé étrangère, Ajouter. -Migration/Update-database again . Cela vous donne une chaîne ininterrompue dans votre migration de modèle. Cela vous sera utile plus tard lorsque vous publiez sur un site actif, car le flux des modifications apportées à votre modèle de données sera intact.

  • J'espère que cela t'aides.
25
RickIsWright

Cette erreur vous indique que vous violez la contrainte de clé étrangère. Pour résoudre vous avez quelques solutions

  1. Corrigez vos données - Quelque part, il existe des enregistrements dans la table Clients qui ont un MedicalGroupId qui n'existe pas dans la table MedicalGroups. Ecrivez une requête pour savoir quels ID ne figurent pas Existent dans la table MedicalGroups et corrigez manuellement les données Vous-même.
  2. Supprimez la contrainte de clé étrangère - Évidemment, si vous supprimez la contrainte de clé étrangère, vous ne serez plus dérangé par ce message. Malheureusement, la base de données n'imposera plus cette relation et pourrait aggraver ce problème à l'avenir.
  3. Créer une contrainte à l'aide de WITH NOCHECK- Vous pouvez créer votre contrainte de clé étrangère à l'aide de l'option WITH NOCHECK. Cette option indique à SQL Server de ne pas appliquer cette contrainte aux données existantes. SQL Server vérifiera cette contrainte lors de futures INSERTS/UPDATES/DELETES.
11
Cory

ce problème apparaît parce que votre table n'est pas vide . vous devez donc ajouter le nouveau champ sans l'attacher comme une clé étrangère . public int? MedicalGroupId {get; ensemble; } . Et exécutez la commande update-database dans la console d'administration du paquet. Remplissez ensuite le champ de cette table (client) avec les bonnes données (la valeur existe dans MedicalGroupsId) . Insérez la ligne pour créer la clé étrangère [ForeignKey ("MedicalGroupId")]. . public MedicalGroups MedicalGroup {get {return _MedicalGroup; } set {_MedicalGroup = value; }} . à la fin, exécutez la commande update-database. Ça va aller.

6
chekib

Pour les autres qui pourraient atterrir ici, il pourrait y avoir une solution très simple si vous utilisez Framework Entity Code-First et essayez simplement d'ajouter une nouvelle colonne obligatoire à une table avec des données existantes. 

Remarque: Avant cela, sachez que vous devrez ajouter une valeur valide à cette nouvelle colonne pour toutes les lignes existantes. Réfléchissez à la valeur que vous ajouterez aux lignes existantes avant de continuer. Vous souhaiterez peut-être fournir une valeur indiquant "Non valide" ou "Inconnu" dans la table de recherche requise. 

Dans votre modèle, définissez la colonne sur nullable en ajoutant le? après l'int. Enregistrez et compilez le modèle. Exécutez Update-Database.

Exemple:

[ForeignKey("Title")]
public int? TitleId { get; set; }

Dans la base de données, mettez à jour la table en remplaçant les valeurs NULL par une valeur de recherche valide. Dans mon cas, j'ai ajouté "Inconnu" à ma table de recherche Titre, puis j'ai modifié en bloc toutes les lignes pour faire référence à cet ID de recherche.

De retour dans votre modèle, supprimez le '?' la colonne n'est donc plus nullable. Enregistrez et compilez le modèle, puis exécutez Update-Database.

Vous devriez maintenant être prêt à partir.

2
GrayDwarf

J'ai eu ce problème aussi avec defaultValue set, a donné:

"L 'objet dépend de la colonne. ALTER TABLE. ALTER COLUMN a échoué car un ou plusieurs objets accèdent à cette colonne". 

Vous avez fini par déplacer AddForeignKey/DropForeignKey vers une nouvelle migration et de les exécuter dans des commandes distinctes de mise à jour de la base de données (n'exécutez pas les deux migrations en une seule, cela a échoué pour moi.) 

    public override void Up()
    {
        CreateTable(
            "dbo.DecisionAccesses",
            c => new
            {
                Id = c.Int(nullable: false),
                Name = c.String(nullable: false, maxLength: 50),
            })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.DecisionPersonStatus",
            c => new
            {
                Id = c.Int(nullable: false),
                Name = c.String(nullable: false, maxLength: 50),
            })
            .PrimaryKey(t => t.Id);

        AddColumn("dbo.DecisionForm_DecisionFields", "DecisionAccessId", c => c.Int(nullable: false, defaultValue: (int)DecisionAccess.Creator));
        AddColumn("dbo.DecisionMatterPersons", "DecisionPersonStatusId", c => c.Int(nullable: false, defaultValue: (int)DecisionAccess.Creator));
        CreateIndex("dbo.DecisionForm_DecisionFields", "DecisionAccessId");
        CreateIndex("dbo.DecisionMatterPersons", "DecisionPersonStatusId");
        //I moved outcommented to next migration and ran the migrations in separate steps to avoid: (The object is dependent on column ALTER TABLE ALTER COLUMN failed because one or more objects access this column)
        //AddForeignKey("dbo.DecisionForm_DecisionFields", "DecisionAccessId", "dbo.DecisionAccesses", "Id", cascadeDelete: true); 
        //AddForeignKey("dbo.DecisionMatterPersons", "DecisionPersonStatusId", "dbo.DecisionPersonStatus", "Id", cascadeDelete: true);
    }


    public override void Down()
    {
        //Moved to next migration
        //DropForeignKey("dbo.DecisionMatterPersons", "DecisionPersonStatusId", "dbo.DecisionPersonStatus");
        //DropForeignKey("dbo.DecisionForm_DecisionFields", "DecisionAccessId", "dbo.DecisionAccesses");
    }
2
Sgedda

En supposant que vos migrations se déroulent dans le bon ordre, la table associée à la clé étrangère sera créée avant la référence. Suivez les étapes suivantes: 

  1. Sauvegarde de la base de données actuelle à partir du studio de gestion SQL (si nécessaire)
  2. Supprimer la base de données du studio de gestion SQL 
  3. Tapez 'Update-Database' dans Visual Studio 'Package Manager Console'
1
Kuldeep Padhiar

Cette erreur peut également se produire si vous avez des enregistrements orphelins dans la table enfant. Nettoyer la base de données devrait résoudre le problème.

Exécutez la commande Add-Migration InitialCreate –IgnoreChanges dans la console de Package Manager. Cela crée une migration vide avec le modèle actuel en tant qu'instantané.

Exécutez la commande Update-Database dans la console Package Manager. Ceci appliquera la migration InitialCreate à la base de données. Dans la mesure où la migration proprement dite ne contient aucune modification, il suffit d'ajouter une ligne à la table __MigrationsHistory, indiquant que cette migration a déjà été appliquée.

Vous pouvez obtenir plus de détails ici: https://msdn.Microsoft.com/en-us/library/dn579398(v=vs.113).aspx

0
Ersin