2013-10-11 10 views
28

Se provo a eliminare una riga "secondaria" ottengo sempre un'eccezione. Ecco uno snipset:EF6.0 "La relazione non può essere modificata perché una o più proprietà della chiave esterna non sono annullabili"

using (var context = new CompanyContext()) 
{ 
    ItemType itemType = context.ItemTypes.FirstOrDefault(i => i.Name == "ServerType"); 
    ItemTypeItem itemTypeItem = itemType.Items.FirstOrDefault(i => i.Name == "DatabaseServer"); 
    itemType.Items.Remove(itemTypeItem); 
    context.SaveChanges(); <=== exception! 
} 

la seguente eccezione viene generata sul metodo SaveChanges().

"La relazione non può essere modificata perché una o più proprietà di chiave esterna non sono annullabili: quando viene apportata una modifica a una relazione, la proprietà di chiave esterna correlata viene impostata su un valore nullo. Se la chiave esterna non supporta valori nulli, è necessario definire una nuova relazione, la proprietà chiave esterna deve essere assegnata a un altro valore non nullo o l'oggetto non correlato deve essere eliminato. "

Entity configurazione

public class ItemTypeConfiguration : NamedEntityConfiguration<ItemType> 
    { 
    public ConfigurationColumn ParentIDColumn; 
    public ConfigurationColumn ValidationPatternColumn; 
    public ItemTypeConfiguration() : base() 
    { 
     ParentIDColumn = new ConfigurationColumn() { Name = "ParentID", Ordinal = base.LastOrdinalPosition + 1 }; 
     ValidationPatternColumn = new ConfigurationColumn() { Name = "ValidationPattern", Length = 1024, Ordinal=base.LastOrdinalPosition + 2}; 
     this.Property(t => t.ParentID) 
     .HasColumnName(ParentIDColumn.Name) 
     .HasColumnOrder(ParentIDColumn.Ordinal); 
     this.HasOptional(t => t.Parent).WithMany().HasForeignKey(u => u.ParentID).WillCascadeOnDelete(false); 
     this.Property(t => t.ValidationPattern) 
     .HasColumnName(ValidationPatternColumn.Name) 
     .HasColumnOrder(ValidationPatternColumn.Ordinal) 
     .HasMaxLength(ValidationPatternColumn.Length); 
    } 
... 


    public class ItemTypeItemConfiguration : NamedEntityConfiguration<ItemTypeItem> 
    { 
    public ConfigurationColumn ItemTypeIDColumn; 
    public ItemTypeItemConfiguration() : base() 
    { 
     ItemTypeIDColumn = new ConfigurationColumn(){Name="ItemTypeID", IsRequired=true, Ordinal= base.LastOrdinalPosition+1}; 
     this.Property(t => t.ItemTypeID) 
     .HasColumnName(ItemTypeIDColumn.Name) 
     .HasColumnOrder(ItemTypeIDColumn.Ordinal); 
     this.HasRequired(t => t.ItemType).WithMany(t=>t.Items).HasForeignKey(u => u.ItemTypeID).WillCascadeOnDelete(true); 
    } 
... 

enter image description here

ho trovato il blog, ma non ho il metodo "DeleteObject".

http://blog.clicdata.com/2013/07/04/the-operation-failed-the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-properties-is-non-nullable/

Tutte le idee? Grazie.

+0

possibile duplicato del [Il rapporto non potrebbe essere cambiato perché uno o più delle proprietà chiave esterna è non annullabile] (http://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-one-or-more-of-the-foreign-key-pro) –

+0

il collegamento è inattivo –

risposta

46

È necessario eliminare ItemTypeItem. Non è possibile rimuoverlo dall'elenco degli articoli poiché non può esistere da solo, perché ha una chiave esterna non nullable che fa riferimento a ItemType (ItemTypeID).

Per eliminare l'ItemTypeItem aggiungere

context.Entry(itemTypeItem).State = EntityState.Deleted; 
+2

che è strano perché io Sono in grado di aggiungere elementi senza fare EntityState.Added ... ma che ha funzionato, grazie! Ora ho bisogno di scoprire come cambio il mio repository per ottenere la stessa cosa. Ho solo provato direttamente dal contesto. EF è una scatola nera, così tanto da imparare !!! – Max

+1

Ho solo capito questa risposta una volta che ho letto la risposta di @Gerry qui sotto, la chiave è di eliminarla da 'context' e non dall'entità genitore ... –

+0

Sono d'accordo con @Max qui, mentre aggiungo nuova entità tu puoi semplicemente aggiungerlo alla raccolta e il contesto db lo tratterà per te. Non è necessario impostare lo stato come 'Aggiunto' Tuttavia, per l'eliminazione non è possibile eliminare dalla raccolta, è necessario eliminarlo dal contesto e contrassegnare lo stato come eliminato ... la sua confusione – LP13

40

Nel quadro dell'entità 6.0 se si rimuove l'entità dal contesto principale impostato che funzionerà. Ad esempio, per rimuovere un'entità di investimento si dovrebbe effettuare le seguenti operazioni:

context.Investments.Remove(entity); 
context.SaveChanges(); 

Questo è diverso da quello di rimuovere il soggetto dal suo genitore/proprietario, come il seguente:

bankAccount.Investments.Remove(entity); 
context.SaveChanges(); 

Ciò gettare la relazione non può essere modificata eccezione elencata sopra. Spero che questo ti aiuti.

17

In entità 6.0 v'è una differenza tra:

context.Investments.Remove(entity); 

e

context.Entry(entity).State = EntityState.Deleted; 

Quando si utilizza il primo ed eliminazioni a catena sono abilitati, EF eseguirà internamente le eliminazioni necessarie delle collezioni bambino. Quando si utilizza la seconda opzione, EF non gestirà le eliminazioni necessarie, ma consentirà di gestire la rebinding/eliminazione di questi oggetti figlio.

+2

Salvato il mio giorno. Ho corretto eliminare a cascata configurato, ma sto ottenendo la stessa eccezione. Più sorprendente, un test di unità verde con SQL Server completo come dimostra il backend, che elimina la sovrapposizione a cascata. Questo commento mi ha fatto riflettere e mi ha aiutato a risolvere il problema: context.Set . Rememove (entity) è preferito quando l'entità era caricato da questa istanza di contesto, mentre context.Entry (entity) .State = Deleted funziona quando si fornisce semplicemente una chiave e si costruisce un'entità stub. –

1

Questo problema si verifica perché si tenta di eliminare la tabella padre, mentre i dati della tabella figlio sono presenti. Risolviamo il problema con l'aiuto dell'eliminazione a cascata.

Nel metodo Create model nella classe dbcontext.

modelBuilder.Entity<Job>() 
       .HasMany<JobSportsMapping>(C => C.JobSportsMappings) 
       .WithRequired(C => C.Job) 
       .HasForeignKey(C => C.JobId).WillCascadeOnDelete(true); 
      modelBuilder.Entity<Sport>() 
       .HasMany<JobSportsMapping>(C => C.JobSportsMappings) 
        .WithRequired(C => C.Sport) 
        .HasForeignKey(C => C.SportId).WillCascadeOnDelete(true); 

Dopo di che, nel nostro API chiamata

var JobList = Context.Job      
      .Include(x => x.JobSportsMappings)          .ToList(); 
Context.Job.RemoveRange(JobList); 
Context.SaveChanges(); 

Cascade opzione di cancellazione cancellare il genitore e genitore tabella figlia correlata con questo semplice codice. Fallo provare in questo modo semplice.

Rimuovere Gamma che ha usato per eliminare l'elenco dei record del database Grazie

Problemi correlati