2013-10-11 14 views
28

Bir "alt" satırı silmeye çalışırsanız, her zaman bir özel durum alırım.EF6.0 "Bir yabancı anahtar özelliklerinin bir veya daha fazla geçersiz olması nedeniyle ilişki değiştirilemedi"

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

aşağıdaki istisna SaveChanges() yöntemine atılır: İşte snipset olduğunu. Bir veya yabancı anahtar özelliklerinin daha olmayan null olduğu için

"ilişkisi değiştirilemiyor. Bir değişiklik ilişkiye yapıldığında, ilgili yabancı anahtar özellik null bir değere ayarlanır. Yabancı anahtar null değerlerini desteklemiyorsa, yeni bir ilişki tanımlanmalı, yabancı anahtar özelliğine sıfırdan başka bir değer verilmemeli veya ilgisiz nesne silinmelidir. "

Varlık Yapılandırma

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

Ben blog buldum ama "NesneSil" yöntemini yok.

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/

Herhangi bir fikir? Teşekkür ederim.

+0

olası yinelenen [bir veya yabancı anahtar özelliklerinin daha olmayan null olduğu için ilişkiye değiştirilemedi] (http://stackoverflow.com/questions/5538974/the-relationship-could-not-be-changed-because-or-more-of-the-foreign-key-pro) –

+0

Bağlantı –

cevap

46

ItemTypeItem öğesini silmeniz gerekir. Öğe listesinden kendisini kaldırmak mümkün değildir, çünkü ItemType (ItemTypeID) öğesine başvuran, geçersiz olmayan bir yabancı anahtar vardır.

ana bağlam işe yarayacak set sizi varlık kaldırırsanız ItemTypeItem varlık çerçevesi 6.0

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

aşağısındadır çünkü bu garip EntityState.Added yapmadan öğeleri ekleyebiliyorum ... ama bu adam çalıştı, teşekkür ederim! Şimdi aynı şeyi elde etmek için depomuzu nasıl değiştirdiğimi bulmalıyım. Sadece doğrudan bağlamdan test ettim. EF böyle bir kara kutu, öğrenecek çok şey var! – Max

+1

Sadece cevabı aşağıda @Gerry tarafından okuduğumda bu cevabı anlıyorum .., anahtar, 'bağlamdan' silmek ve varlık ana öğesinden değil ... –

+0

Burada yeni varlık eklerken @Max ile katılıyorum sadece koleksiyona ekleyebilir ve db içeriği sizin için bu yolu tutacaktır. "Silinmiş" olarak durumu ayarlamak zorunda değilsiniz. Ancak silme işlemi için sadece koleksiyondan silemezsiniz, bağlamdan silmeniz ve durumu silinmiş olarak işaretlemeniz gerekir ... karıştırıcı – LP13

40

eklemek silin.

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

Bu aşağıdaki gibi üst/sahibinden varlık çıkarmaya çalışmadan farklıdır:

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

Bu fırlatır örnek bir yatırım varlık kaldırmak için için aşağıdakileri yapacağını yukarıda listelenen ilişki istisnası değiştirilemedi. Bu yardımcı olur umarım. EF içten çocuk koleksiyonlarının gerekli siler gerçekleştirecek, birinci ve basamaklı siler etkindir kullanırken

context.Investments.Remove(entity); 

ve

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

: varlık 6.0'da

17

arasında bir fark yoktur. İkinci seçeneği kullanırken, EF gerekli silme işlemlerini gerçekleştirmeyecek, ancak bu alt nesnelerin yeniden oluşturulmasını/silinmesini sağlayabilirsiniz.

+2

Günümü kurtardı. Yapılandırılan doğru basamaklı silme var ama aynı istisna alıyorum. Daha şaşırtıcı, arka uçta olduğu gibi tam gelişmiş SQL Server ile yeşil bir birim testi, bu kaskat silme vuruşlarını gerçekleştirdi. Bu yorum beni düşünmemize neden oldu ve sorunu düzeltmeme yardımcı oldu: context.Set . Varlık (varlık), varlık context.ntry (varlık) .State = Silme, yalnızca bir anahtar sağladığında ve bir Saplama Varlığı oluşturulduğunda çalışır. –

1

Bu sorun, ana tabloyu silme denememizden kaynaklanıyor çünkü çocuk tablo verileri mevcut. Sorunu kaskad silme yardımı ile çözüyoruz.

dbcontext sınıfında model oluşturma yönteminde.bu basit kod ile de ebeveyn ilgili alt tablo ebeveyn silmek API Çağrısı

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

Cascade silmek seçenek olarak Bundan sonra

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

. Bunu basit bir şekilde deneyin.

veritabanı sayesinde kayıtların listesini silmek için kullanılan

Kaldır Aralığı

İlgili konular