EF 4.1 RC:奇怪的级联删除

时间:2011-03-23 09:13:45

标签: ef-code-first cascading-deletes entity-framework-4.1 fluent-interface

我必须承认,EF 4.1 RC Codefirst,DataAnnotations和FluentAPI的功能对我来说仍然是压倒性的。有时我真的不知道我在做什么;-)请看下面的POCO:

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

我认为这意味着:每个国家都需要一种货币。此货币可能有零个,一个或多个国家/地区(可选)。每当我删除一种货币时,相应的国家(如果有的话)都不会被级联删除。

令人惊讶的是,如果删除相应的货币,给定的方法仍会级联删除国家/地区。谁能告诉我我想念的是什么?

1 个答案:

答案 0 :(得分: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();
    }          
  }
}

保存时会出错,因为您删除的是必需的外键。