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로 설정됩니다. 즉, 통화를 삭제하면 해당 국가도 삭제됩니다. 하지만 내 경우에는 이건 이 아니고 내가 원하는 바가입니다.

나는 CASCADE는 삭제하지 않도록하기 위해 FluentAPI에서 일부 코드를 내놓았다 : 모든 국가 통화가 필요합니다
modelBuilder.Entity<Country>() 
      .HasRequired(cou => cou.Currency) 
      .WithOptional() 
      .WillCascadeOnDelete(false); 

나는 이것이 의미 생각했다. 이 통화에는 0 개 또는 하나 이상의 국가가 할당 될 수 있습니다 (선택 사항). 통화를 삭제할 때마다 해당 국가 (있을 경우)가 삭제되지 않습니다.

놀랍게도 해당 방법을 사용하면 해당 통화를 삭제해도 일정한 방식으로 국가를 삭제할 수 있습니다. 아무도 내가 놓친 걸 말해 줄 수 있니?

답변

5

먼저 통화를 국가에서 필수 입력란으로 지정 했으므로 통화를 삭제할 수 없습니다. [Required]를 제거해야합니다.

둘째, 모델 빌더는 다음이 필요합니다

Currency c = context.Currencies.FirstOrDefault(); 

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

       context.Currencies.Remove(c); 

       context.SaveChanges(); 

[편집] : 셋째

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

, 당신은 아이들의에서 명시 적으로 삭제 된 개체에 대한 참조를 제거해야 번역에서 잃어버린 무언가가 의심 스럽기 때문에 계단식 삭제 기능이 어떻게 작동 하는지를 보여주는 완전한 코드를 찾으십시오.

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

답장을 보내 주셔서 감사합니다. 불행히도 나는 아마 충분히 자신을 분명히하지 않았다 : 내 모델에서 모든 국가는 통화가 필요합니다. 따라서 통화가 [필수]로되어 있어야합니다. 즉, 적어도 하나의 국가가 할당 된 경우 통화를 삭제할 수 없다는 사실에 전적으로 행복합니다. 그러나이 예상대로 작동하지 않습니다. 해당 통화를 삭제해도 계단식 삭제로 인해 국가가 삭제됩니다. 그리고 이것은 좋지 않습니다. 유창한 API 문으로 CASCADE DELETE를 해제 한 것으로 생각하기 때문에 직접 설명 할 수 없습니다. 이 경우 – Ingmar

+0

을 입력하고 [Required]를 그대로두면 .hasoptional 대신 .HasRequired를 사용하고 country가있는 통화를 삭제할 수 없습니다. – Xhalent

+0

@Xhalent : .HasOptional 대신 .HasOptional을 사용해야합니다. 원래 유창한 API 성명서? 확실합니까? 이제 나는 완전히 혼란 스럽다. 모든 통화에 반드시 국가가 있어야 함을 의미하지 않습니까? 그렇다면 통화가 국가 (0, 1, 무제한)를 할당받을 수 있다고 말하는 비즈니스 규칙과 일치하지 않습니다. – Ingmar

관련 문제