2013-10-11 2 views
28

Wenn ich versuche, eine "untergeordnete" Zeile zu löschen, bekomme ich immer eine Ausnahme. Hier ist ein snipset:EF6.0 "Die Beziehung konnte nicht geändert werden, weil eine oder mehrere Eigenschaften des Fremdschlüssels nicht nullfähig sind"

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

Die folgende Ausnahme auf der SaveChanges() Methode geworfen wird.

"Die Beziehung konnte nicht geändert werden, da eine oder mehrere Fremdschlüsseleigenschaften nicht nullfähig sind. Wenn eine Beziehung zu einer Beziehung geändert wird, wird die zugehörige Fremdschlüsseleigenschaft auf einen Nullwert gesetzt. Wenn der Fremdschlüssel keine Nullwerte unterstützt, muss eine neue Beziehung definiert werden, der Fremdschlüsseleigenschaft muss ein anderer Wert ungleich Null zugewiesen werden, oder das nicht verwandte Objekt muss gelöscht werden. "

Entity Konfiguration

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

fand ich den Blog aber ich habe nicht die "DeleteObject" -Methode.

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/

Irgendwelche Ideen? Vielen Dank.

+0

möglich Duplikat [Die Beziehung konnte nicht geändert werden, da eine oder mehrere der Fremdschlüsseleigenschaften ist nicht-nullable] (http://stackoverflow.com/questions/5538974/the-relationship-could-not-changed-because-one-or-more-of-the-foreign-key-pro) –

+0

der Link ist down –

Antwort

46

Sie müssen das ItemTypeItem löschen. Es ist nicht möglich, es einfach aus der Elementeliste zu entfernen, da es nicht selbst existieren kann, da es einen nicht nullbaren Fremdschlüssel enthält, der auf ItemType (ItemTypeID) verweist.

löschen die ItemTypeItem

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

das ist komisch, weil ich bin in der Lage, Elemente hinzuzufügen, ohne EntityState.Added ... aber das funktionierte Mann, danke! Jetzt muss ich herausfinden, wie ich mein Repository ändere, um dasselbe zu erreichen. Ich habe nur direkt aus dem Kontext getestet. EF ist so eine Black Box, so viel zu lernen !!! – Max

+1

Ich verstehe nur diese Antwort, sobald ich die Antwort von @Gerry unten lesen .., der Schlüssel ist, es aus 'Kontext' und nicht von der Entität Eltern zu löschen ... –

+0

Ich stimme mit @Max hier, während neue Entität Sie hinzufügen kann es nur zur Sammlung hinzufügen, und db-Kontext wird das für Sie tun. Sie müssen den Status nicht als 'Hinzugefügt' setzen. Zum Löschen können Sie jedoch nicht einfach aus der Sammlung löschen, Sie müssen es aus dem Kontext löschen und den Status als gelöscht markieren ... es ist verwirrend – LP13

40

Im Entity Framework 6.0, wenn Sie an das Unternehmen entfernen hinzufügen aus dem Kontext es gesetzt arbeiten. Zum Beispiel eine Investition Einheit zu entfernen, würden Sie wie folgt vor:

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

Dies als der Versuch, unterscheidet das Unternehmen von seinen Eltern/Eigentümer, wie folgt zu entfernen:

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

Dies wird werfen den Die oben genannte Beziehung konnte nicht geändert werden. Hoffe das hilft.

17

In Einheit 6.0 gibt es einen Unterschied zwischen:

context.Investments.Remove(entity); 

und

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

Wenn die ersten mit und Löschweiter aktiviert sind, EF die notwendigen Löschungen von Kindern Sammlungen intern durchzuführen. Wenn Sie die zweite Option verwenden, wird EF nicht die erforderlichen Löschvorgänge behandeln, aber Sie können das erneute Binden/Löschen dieser untergeordneten Objekte verarbeiten.

+2

Mein Tag gerettet. Ich habe richtiges kaskadierendes Löschen konfiguriert, bekomme aber die selbe Ausnahme. Überraschender ist, dass ein grüner Komponententest mit vollem SQL Server als Backend beweist, dass das kaskadierende Löschen einsetzt. Dieser Kommentar ließ mich denken und half mir, das Problem zu beheben: context.Set .Remove (entity) wird bevorzugt, wenn die Entity war wurde zuvor aus dieser Kontextinstanz geladen, während context.Entry (entity) .State = Deleted funktioniert, wenn nur ein Schlüssel bereitgestellt und eine Stub-Entität konstruiert wird. –

1

Dieses Problem tritt auf, weil wir versuchen, die Elterntabelle zu löschen, die noch untergeordnete Tabellendaten vorhanden ist. Wir lösen das Problem mit Hilfe von Kaskadenlöschung.

In Modell Create-Methode in Dbcontext-Klasse.

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

Danach, in unserem API-Aufruf

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

Cascade löschen Option, um die Eltern löschen sowie Eltern damit verbundene untergeordnete Tabelle mit diesem einfachen Code. Versuche es auf diese einfache Art und Weise.

Remove Bereich, die die Liste der Datensätze in der Datenbank Dank für das Löschen verwendet

Verwandte Themen