2014-01-23 3 views
11

여기에도 이와 비슷한 질문이 몇 개 있지만 간략한 시나리오에서 누락 된 부분을 확인하는 데 문제가 있습니다.Entity Framework 6 : 코드 첫 번째 계단식 삭제

의 내가 영리하게 자신의 이름을 딴, 다음과 같은 테이블이 있다고 가정 해 봅시다 : 결과 클래스와

'JohnsParentTable' (Id, Description) 
'JohnsChildTable' (Id, JohnsParentTableId, Description) 

내가 부모 테이블의 행에이 데이터베이스에 너무

public class JohnsParentTable 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public virtual ICollection<JohnsChildTable> JohnsChildTable { get; set; } 

    public JohnsParentTable() 
    { 
     JohnsChildTable = new List<JohnsChildTable>(); 
    } 
} 

internal class JohnsParentTableConfiguration : EntityTypeConfiguration<JohnsParentTable> 
{ 
    public JohnsParentTableConfiguration() 
    { 
     ToTable("dbo.JohnsParentTable"); 
     HasKey(x => x.Id); 
     Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); 
    } 
} 

public class JohnsChildTable 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
    public int JohnsParentTableId { get; set; } 
    public JohnsParentTable JohnsParentTable { get; set; } 
} 

internal class JohnsChildTableConfiguration : EntityTypeConfiguration<JohnsChildTable> 
{ 
    public JohnsChildTableConfiguration() 
    { 
     ToTable("dbo.JohnsChildTable"); 
     HasKey(x => x.Id); 
     Property(x => x.Id).HasColumnName("Id").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     Property(x => x.Description).HasColumnName("Description").IsRequired().HasMaxLength(50); 
     HasRequired(a => a.JohnsParentTable).WithMany(c => c.JohnsChildTable).HasForeignKey(a => a.JohnsParentTableId); 
    } 
} 

처럼 보이는 이 부모에 연결된 자식 테이블의 두 행과 함께 1의 ID. 내가 이렇게하면 :

var parent = db.JohnsParentTable.FirstOrDefault(a => a.Id == 1) 

개체가 올바르게 채워집니다. 나는이 행을 삭제하려고 경우 :

var parent = new Data.Models.JohnsParentTable() { Id = 1 }; 
db.JohnsParentTable.Attach(parent); 
db.JohnsParentTable.Remove(parent); 

db.SaveChanges(); 

엔티티 프레임 워크는 다음 실행을 시도 :

DELETE [dbo].[JohnsParentTable] 
WHERE ([Id] = @0) 
-- @0: '1' (Type = Int32) 
-- Executing at 1/23/2014 10:34:01 AM -06:00 
-- Failed in 103 ms with error: The DELETE statement conflicted with the REFERENCE constraint "FK_JohnsChildTable_JohnsParentTable". The conflict occurred in database "mydatabase", table "dbo.JohnsChildTable", column 'JohnsParentTableId'. 
The statement has been terminated. 

내 질문은 정확히 내가 엔티티 프레임 워크가 삭제해야 함을 알 수 있도록 실종 누구인지 부모를 삭제하기 전에 'JohnsChildTable'행을 삭제 하시겠습니까?

답변

11

그것은 당신이 엔티티 프레임 워크는 아이들을 삭제할지 여부에 따라, 또는 데이터베이스가 알아서 할.

EF가 모든 하위 항목에 대해 delete 문을 생성하고 상위 항목을 삭제하기 전에 EF를 실행하려면 모든 하위 항목을 먼저 메모리에로드해야합니다.

따라서 단순히 채워진 키로 "더미"엔티티를 만들고 자식을 삭제할 수는 없습니다.

작동하려면 데이터베이스에서 삭제 작업을 처리하도록해야합니다.

그러나 자식 테이블의 외래 키는 계단식 삭제를 사용하도록 설정해야합니다. 그렇다면 Entity Framework는 부모에 대한 delete 문을 만들고 데이터베이스는 자식을 삭제하는 것을 알고 있습니다.

Entity Framework는 사용자의 경우와 같이 관계가 필요할 경우 기본적으로 계단식 삭제가 활성화 된 외래 키를 만듭니다. 외래 키는 null 일 수 없습니다.

데이터베이스를 직접 만든 경우 데이터베이스를 사용하도록 설정해야합니다.

-1

Visual Studio에서 모델 파일을 엽니 다. 상위 - 하위 관계를 마우스 오른쪽 단추로 클릭하고 속성을 선택하십시오.

End1 OnDelete 속성에서 값은 None입니다. 다른 옵션은 계단식입니다. 그것을 설정하십시오. 이제 Parent를 삭제하면 해당 삭제가 자식으로 캐스케이드됩니다.

enter image description here

건배 -

+8

영업 문제는 코드 첫 번째입니다. 이 솔루션은 Model First에만 적합합니다. – vidalsasoon

15

OnModelCreating 메서드를 재정의하고이 코드를 추가하는 것이 더 좋습니다.

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<JohnsChildTable>() 
       .HasRequired(t=>t.JohnsParentTable) 
       .WithMany(t=>t.JohnsChildTables) 
       .HasForeignKey(d=>d.JohnsParentTableId) 
       .WillCascadeOnDelete(true); 

      base.OnModelCreating(modelBuilder); 
} 

은 내가 (사실)가 true WillCascadeOnDelete로 설정 한

+0

그냥 경고 : 위의 코드 **는 ** 메모리에로드되지 않은 EF 캐스케이드 자식을 삭제하지 않습니다 **. – Riva

관련 문제