2016-08-23 2 views
3

내 Asp.Net Mvc 프로젝트에 4 개의 모델 클래스가 있습니다. 엔티티 프레임 워크 코드 우선 (자동 마이그레이션)을 사용하고 있습니다. 나는 update-database 명령을 실행할 때 다음과 같은 오류가 발생합니다.Entity Framework 코드 첫 번째 여러 계단식 오류

사이클 또는 여러 개의 계단식 경로를 일으킬 수 테이블 '티켓'에 FOREIGN KEY 제약 조건 'FK_dbo.Tickets_dbo.Users_CreatedUserId'를 소개합니다. NO DELETE NO ACTION 또는 UP UP NO NO ACTION을 지정하거나 다른 FOREIGN KEY 제약 조건을 수정하십시오. 제약 조건 또는 인덱스를 만들 수 없습니다. 이전 오류를 참조하십시오.

무엇이 문제인가?

//Company Class 
public class Company 
{ 
    public int Id { get; set; } 

    [Required, StringLength(100)] 
    public string Title { get; set; } 

    public virtual ICollection<User> Users { get; set; } = new HashSet<User>(); 
} 

//User Class 
public class User 
{ 
    public int Id { get; set; } 

    [Required, StringLength(50)] 
    public string UserName { get; set; } 

    [Required, StringLength(100)] 
    public string FullName { get; set; } 

    public int CompanyId { get; set; } 
    public virtual Company Company { get; set; } 
} 

//Ticket Class 
public class Ticket 
{ 
    public int Id { get; set; } 

    [Required] 
    public DateTime CreationDate { get; set; } 

    [Required, StringLength(100)] 
    public string Title { get; set; } 

    public bool IsClosed { get; set; } 

    public int CreatedUserId { get; set; } 
    public virtual User CreatedUser { get; set; } 

    public virtual ICollection<TicketMessage> Messages { get; set; } = new HashSet<TicketMessage>(); 
} 

//TicketMessage Class 
public class TicketMessage 
{ 
    public int Id { get; set; } 

    public DateTime Date { get; set; } 

    [Required] 
    public string Message { get; set; } 

    public int UserId { get; set; } 
    public virtual User User { get; set; } 

    public int TicketId { get; set; } 
    public virtual Ticket Ticket { get; set; } 

} 
+0

'Users'테이블에는 많은 Tickets과 많은 TicketMessages가 있고 동시에 Ticket에는 많은 TicketMessages가 있기 때문입니다. – Szer

+0

예, 그렇게 될 것입니다. 사용자는 티켓 및 티켓 메시지를 작성할 수 있기 때문입니다. –

+0

그러나 특정 'User'를 삭제하면 SQL 엔진이 어떻게 해야할지 알 수 없습니다. 말 그대로 "ON DELETE NO ACTION"을 지정하거나 커스텀'delete trigger'를 만드십시오. – Szer

답변

1

한 모델 (상위)에서 레코드를 삭제하면 해당 레코드와 관련된 하위 모델의 모든 레코드가 삭제됩니다. 이 예에서 Users 모델은 많은 Tickets 및 TicketMessages를 가진 부모이므로 사용자를 삭제하면 연쇄 적 삭제가 모든 사용자 Tickets 및 TicketMessages도 삭제합니다. 모델에 탐색 속성이 있으면 EF는 자동으로 외래 키를 할당합니다. 외래 키는 모델 간의 관계를 만들고 '자식'모델의 레코드가 삭제하려고하는 레코드의 기본 키로있는 외래 키에 종속되어있을 때 한 모델에서 레코드를 삭제할 수 없음을 의미합니다.

사용자 의견에 명시된 바와 같이 사용자 모델이 Tickets 및 TicketMessages와 일대 다 많은 관계를 갖고있는 경우 Ticket 모델은 TicketMessages와 일대 다 많은 관계가 있습니다. 즉, 사용자 레코드를 삭제하면 해당 UserID와 연결된 TicketMessage 및 TicketMessage가 사용자 ID의 캐스케이드에 의해 삭제되지 않는 TickedMessage를 사용할 수 있다는 점을 제외하고는 해당 TicketMessage 및 TicketMessages와 TicketMessage와 관련된 모든 TicketMessages 및 티켓이 삭제된다는 것을 의미합니다 . 따라서 외래 키 관계가 깨지기 때문에 오류가 발생합니다.

는 두 가지 해결책이 있습니다

1 - 디자인을 수정하여 TicketMessages 모델은 이미 티켓 ID를 통해, 티켓과 관계가 있으므로 사용자 ID가 티켓 모델에서 티켓 ID와 연관된로 사용자 ID와 관계가 . 따라서 TicketMessage 모델에서 UserID 관계를 제거 할 수 있으므로 필요하지 않습니다. 그러면 문제점이 해결됩니다. 그것은 당신의 디자인이 문제이기 때문에 이것은 정말로 내 마음 속의 올바른 해결책입니다.

2 - 당신은 내가 인식 할 수없는 어떤 이유로 그 관계를 유지하려는 경우, 당신은 캐스케이드 사용하여 완전히 삭제하지 않도록 설정할 수 있습니다

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
    modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
} 

두 줄

이 많은 폭포에 많은 많은에게 모두 하나를 제거 삭제 규칙. 당신은 당신이 적합하다고 생각한대로 그들을 지키거나 제거 할 수 있습니다.

또한 사용하여 단일 캐스케이드 삭제 관계를 제거 할 수 있습니다 다음

modelBuilder.Entity<ParentEntity>() 
.HasMany(p => p.Children) 
.WithRequired() 
.HasForeignKey(c => c.ParentEntityId) 
.WillCascadeOnDelete(false); 

내가 매우 추천 솔루션 1, 당신의 TicketMessages 모델에서 사용자 ID를 제거하십시오 TicketMessages 이미 사이의 관계를 통해 사용자 ID에 연결되어 있습니다 TicketMessages 모델과 Ticket 모델.

편집 - TicketMessages와 User 간의 관계가 그 사람이 티켓을 만든 사용자와 다른 사람 일 때 누가 메시지를 작성했는지를 나타낼 수 있습니다. 그렇다면 사용자 테이블과의 관계를 제거하고 티켓 카드가 생성 될 때 해당 티켓 메시지와 관련된 모든 사용자 정보를 채울 수있는 필드를 사용하는 것이 좋습니다 (예 : 이름.또는 사용자 ID 필드가있을 수 있지만 탐색 속성이 없으면 외래 키 관계를 제거 할 수 있습니다. 정보를 검색 할 때이 UserID를 User 테이블의 UserID와 일치 시켜서 사용자 정보를 호출 할 수 있습니다.

1

답변 해 주셔서 감사합니다. Rob! 다음 코드로이 문제를 해결했습니다.

modelBuilder.Entity<User>() 
      .HasMany(e => e.TicketMessages) 
      .WithRequired(e => e.User) 
      .WillCascadeOnDelete(false); 
관련 문제