4

我不得不承認,EF 4.1 RC Codefirst,DataAnnotations和FluentAPI的功能對我來說仍然非常重要。有時候,我真的不知道我在做什麼;-)請看下面波蘇斯:EF 4.1 RC:奇怪的級聯刪除

public class Country 
{ 
    [Key] 
    public Guid ID { get; set; } 

    [Required] 
    public virtual Currency Currency { get; set; } 
} 

public class Currency 
{ 
    [Key] 
    public Guid ID { get; set; } 

    public virtual ICollection<Country> Countries { get; set; } 
} 

總體思路:每個國家都需要有一個貨幣。但是貨幣根本不需要分配給一個國家。

如果讓EF創建相應的數據庫,則按照慣例將關係設置爲CASCADE DELETE。換句話說:如果你刪除一個貨幣,相應的國家也會被刪除。但在我的情況下,這是而不是我想要的。

我爲了想出了FluentAPI一些代碼來禁用CASCADE DELETE:

modelBuilder.Entity<Country>() 
      .HasRequired(cou => cou.Currency) 
      .WithOptional() 
      .WillCascadeOnDelete(false); 

我認爲這意味着:每一個國家都需要一個貨幣。此貨幣可能有零個,分配有一個或多個國家(可選)。每當我刪除貨幣時,相應的國家(如果有的話)不會被級聯刪除。

令人驚訝的是,如果我刪除相應的貨幣,給定的方法仍然會級聯刪除一個國家。有人可以告訴我我錯過了什麼嗎?

回答

5

首先,您已將貨幣指定爲國家/地區的必填字段,因此您無法刪除貨幣。你需要刪除[必須]。

其次,你的模型生成需要以下條件:

modelBuilder.Entity<Country>() 
      .HasRequired(cou => cou.Currency) //note optional, not required 
      .WithMany(c=>c.Countries)   //define the relationship 
      .WillCascadeOnDelete(false); 

第三,你需要顯式刪除提及要刪除的實體從它的孩子們:

Currency c = context.Currencies.FirstOrDefault(); 

       c.Countries.Clear(); //these removes the link between child and parent 

       context.Currencies.Remove(c); 

       context.SaveChanges(); 

[編輯] 因爲我懷疑翻譯中有些東西丟失了,所以找到完整的代碼來演示如何不進行級聯刪除。

public class Country{ 
    [Key] 
    public Guid ID { get; set; } 

    public virtual Currency Currency { get; set; } 
} 

public class Currency{ 
    [Key] 
    public Guid ID { get; set; } 

    public virtual ICollection<Country> Countries { get; set; } 
} 


public class MyContext : DbContext{ 
    public DbSet<Currency> Currencies { get; set; } 
    public DbSet<Country> Countries { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder){ 
    modelBuilder.Entity<Country>() 
    .HasRequired(country => country.Currency) 
    .WithMany(currency => currency.Countries) 
    .WillCascadeOnDelete(false); 
    } 
} 

class Program{ 
    static void Main(string[] args){ 
    Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0"); 

    Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>()); 

    using (MyContext context1 = new MyContext()){ 
     Currency c = new Currency{ID = Guid.NewGuid()}; 

     context1.Currencies.Add(c); 

     c.Countries = new List<Country>(); 

     c.Countries.Add(new Country{ID = Guid.NewGuid()}); 

     context1.SaveChanges(); 
    } 

    using (MyContext context2 = new MyContext()){ 
    Currency c = context2.Currencies.FirstOrDefault(); 

    context2.Currencies.Remove(c); 

    //throws exception due to foreign key constraint 
    //The primary key value cannot be deleted 
    //because references to this key still exist. 
    //[ Foreign key constraint name = Country_Currency ] 

    context2.SaveChanges(); 
    }   
    } 
} 

您將在保存時發生錯誤,因爲您刪除了一些必需的外鍵。

+0

謝謝你的回覆,Xhalent。不幸的是,我可能沒有把自己弄清楚:在我的模型中,每個國家都需要一種貨幣。所以,我真的需要貨幣是[必需的]。換句話說:如果至少有一個國家被分配到,我很高興不能刪除貨幣。但是,這不符合預期。如果刪除相應貨幣,級聯刪除仍會刪除一個國家/地區。這並不好,我也無法向我自己解釋,因爲我認爲我通過流利的API語句關閉了CASCADE DELETE。 – Ingmar 2011-03-23 09:44:13

+0

在這種情況下,保留[必需],並修改modelBuilder使用.HasRequired而不是.Hasoptional,並且您將無法刪除具有國家/地區的貨幣 – Xhalent 2011-03-23 10:19:04

+0

@Xhalent:我應該使用.HasRequired而不是.HasOptional原始的流利的API聲明?你確定?現在我完全困惑。那不是說每個貨幣都必須有一個國家嗎?如果是這樣,那就不符合我的業務規則,即表示貨幣可以有一個國家分配(零,一,無限)。 – Ingmar 2011-03-23 17:29:47