Entity Framework L’istruzione ALTER TABLE è in conflitto con il vincolo FOREIGN KEY

All’aggiornamento del database in Entity Framework, prima migrazione del codice, ricevo questo errore:

L’istruzione ALTER TABLE era in conflitto con il vincolo FOREIGN KEY “FK_dbo.Clients_dbo.MedicalGroups_MedicalGroupId”. Il conflitto si è verificato nel database “hrbc”, nella tabella “dbo.MedicalGroups”, nella colonna “Id”.

Questa è la mia class:

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; } } } 

Ecco la mia seconda class:

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

E questa è la mia migrazione che sto cercando di applicare:

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

Verificare che non vi siano dati esistenti nel database in conflitto con il vincolo FK che causano il fallimento della creazione.

Penso che @Cory ti stesse avvicinando alla soluzione corretta, non ti sei limitato a investigare.

Nel codice add-migration, la migrazione è probabilmente generata

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

Notare nullable: falso; Se il tuo modello ha un ID di int invece di int? (nullable int) il codice di migrazione imposterà nullable su false. Il tuo modello mostra che stai usando un int non nullable che ha come valore predefinito 0 e probabilmente non hai una chiave esterna con valore 0.

A questo punto, è necessario creare un valore predefinito, esistente nella tabella delle chiavi esterne o Creare il vincolo senza controllo se si sta utilizzando SQL Server per creare il vincolo. Ricorda questo però: se decori la tua proprietà con un attributo [DefaultValue (0)], non cambierà i dati esistenti, come farebbe una colonna SQL Add, se è stato specificato un valore predefinito.

Vi consiglio di cambiare la vostra class del modello per consentire un valore nullable int. Quindi, nel metodo seed, creare un metodo semplice con dbcontext per aggiornare la nuova colonna con un valore predefinito, poiché l’attributo [DefaultValue] nelle annotazioni dei dati non modificherà i dati.

Aggiungi-Migrazione / Aggiorna-Database per creare la colonna e il vincolo. Quindi, modificare il modello se si desidera consentire un int non nullable e presumendo di aver modificato tutte le righe su un valore valido per la chiave esterna, Add-Migration / Update-database di nuovo. Questo ti dà una catena ininterrotta nella migrazione del tuo modello. Ci tornerà utile più tardi quando pubblichi su un sito attivo, perché il stream delle modifiche del modello dati sarà intatto.

  • Spero che questo ti aiuti.

Questo errore ti sta dicendo che stai violando il vincolo della chiave esterna. Per risolvere ci sono alcune soluzioni

  1. Correggi i tuoi dati – Da qualche parte ci sono record nella tabella Clients che hanno un MedicalGroupId che non esiste nella tabella MedicalGroups . Scrivi una query per scoprire quali ID non esistono nella tabella MedicalGroups e per correggere manualmente i dati.
  2. Rimuovi il vincolo di chiave esterna – Ovviamente se rimuovi il vincolo di chiave esterna non sarai più disturbato da questo messaggio. Sfortunatamente il database non applicherà più questa relazione e potrebbe peggiorare questo problema in futuro.
  3. Creare un vincolo utilizzando WITH NOCHECK – È ansible creare il vincolo di chiave esterna utilizzando l’opzione WITH NOCHECK . Questa opzione indica a SQL Server di non applicare questo vincolo ai dati esistenti. SQL Server controllerà questo vincolo in qualsiasi futuro INSERTI / AGGIORNAMENTI / DELETE.

questo problema appare perché la tua tabella non è vuota. quindi aggiungi il nuovo campo senza associarlo come chiave esterna. int pubblico? MedicalGroupId {get; impostato; } .Eseguire il comando update-database nella console di gestione dei pacchetti. Quindi riempire il campo in questa tabella (client) con i dati corretti (il valore esiste in MedicalGroupsId). Inserisci la linea per creare la chiave esterna [ForeignKey (“MedicalGroupId”)] public Medical MedicalGroups MedicalGroup {get {return _MedicalGroup; } set {_MedicalGroup = value; }} . alla fine esegui il comando update-database. Sarà ok.

Ho avuto la soluzione del mio problema. Il problema sono i “dati” che ho nella tabella dei miei clienti. Poiché la tabella dei miei clienti ha valori di medicalgroupid che in realtà non esistono, è per questo che mi dà errore sul vincolo di chiave esterna.

 Update Client set MedicalGroupId = NULL 

Ho avuto questo problema anche con il set di defaultValue, ha dato:

“L’object dipende dalla colonna ALTER TABLE ALTER COLUMN non è riuscito perché uno o più oggetti accedono a questa colonna”.

Finito lo spostamento di AddForeignKey / DropForeignKey in una nuova migrazione e li ho eseguiti in comandi separati del database di aggiornamento (non eseguire l’escalation di entrambe le migrazioni in un unico comando, quindi non ha funzionato correttamente).

  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"); } 

Supponendo che le migrazioni siano nell’ordine corretto, ovvero la tabella associata alla chiave esterna verrà creata prima del riferimento. Segui i seguenti passi:

  1. Backup del database corrente da SQL Management Studio (se richiesto)
  2. Elimina il database dallo studio di gestione SQL
  3. Digitare “Update-Database” in Visual Studio “Console Gestione pacchetti”

Per gli altri che potrebbero atterrare qui, potrebbe esserci una soluzione davvero semplice se si utilizza Code-First Entity Framework e si sta semplicemente tentando di aggiungere una nuova colonna richiesta a una tabella con dati esistenti.

Nota: prima di farlo, è sufficiente sapere che sarà necessario aggiungere un valore valido a questa nuova colonna per tutte le righe esistenti. Pensa a quale valore aggiungerai alle righe esistenti prima di procedere. Si consiglia di fornire un valore che indica “Invalido” o “Sconosciuto” nella tabella di ricerca richiesta.

Nel tuo modello, imposta la colonna su Nullable aggiungendo il? dopo l’int. Salva e compila il modello. Esegui il database di aggiornamento.

Esempio:

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

Eseguire il comando Add-Migration InitialCreate -IgnoreChanges in Package Manager Console. Ciò crea una migrazione vuota con il modello corrente come un’istantanea.

Eseguire il comando Update-Database in Package Manager Console. Ciò applicherà la migrazione InitialCreate al database. Poiché la migrazione effettiva non contiene alcuna modifica, verrà semplicemente aggiunta una riga alla tabella __MigrationsHistory che indica che questa migrazione è già stata applicata.

È ansible ottenere maggiori dettagli qui: https://msdn.microsoft.com/en-us/library/dn579398(v=vs.113).aspx