FOREIGN KEY 제약 조건을 도입하면 사이클 또는 여러 계단식 경로가 발생할 수 있습니다. 왜 그렇습니까?
나는 이것을 잠시 동안 레슬링 해 왔으며 무슨 일이 일어나고 있는지 알 수 없습니다. 측면 (일반적으로 2)을 포함하는 카드 엔터티가 있으며 카드와 측면 모두 스테이지가 있습니다. EF Codefirst 마이그레이션을 사용하고 있으며이 오류로 마이그레이션이 실패합니다.
테이블 'Sides'에 FOREIGN KEY 제약 조건 'FK_dbo.Sides_dbo.Cards_CardId'를 도입하면 사이클 또는 여러 계단식 경로가 발생할 수 있습니다. ON DELETE NO ACTION 또는 ON UPDATE NO ACTION을 지정하거나 다른 FOREIGN KEY 제약 조건을 수정하십시오.
내 카드 엔티티는 다음과 같습니다 .
public class Card
{
public Card()
{
Sides = new Collection<Side>();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection<Side> Sides { get; set; }
}
내 측 실체는 다음과 같습니다 .
public class Side
{
public Side()
{
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int SideId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
public int CardId { get; set; }
[ForeignKey("CardId")]
public virtual Card Card { get; set; }
}
그리고 여기 내 스테이지 엔티티가 있습니다 :
public class Stage
{
// Zero
public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
// Ten seconds
public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");
public static IEnumerable<Stage> Values
{
get
{
yield return ONE;
yield return TWO;
}
}
public int StageId { get; set; }
private readonly TimeSpan span;
public string Title { get; set; }
Stage(TimeSpan span, string title)
{
this.span = span;
this.Title = title;
}
public TimeSpan Span { get { return span; } }
}
이상한 점은 Stage 클래스에 다음을 추가하면 다음과 같습니다.
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
마이그레이션이 성공적으로 실행됩니다. SSMS를 열고 테이블을 보면 (예상 / 원하는대로) Stage_StageId
추가되었지만 Cards
(예상 Sides
되지 않은)에 대한 참조가 포함되어 있지 Stage
않음을 알 수 있습니다.
내가 추가하면
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
내 사이드 클래스에 테이블에 StageId
열이 추가 된 것을 볼 수 Side
있습니다.
이것은 작동하지만 이제는 내 응용 프로그램 전체에서에 대한 참조가 Stage
포함되어 있으며 SideId
경우에 따라 전혀 관련이 없습니다. 난 그냥 내주고 싶습니다 Card
및 Side
단체 Stage
참조 속성 가능한 경우와 무대 클래스 오염없이 무대 위의 클래스를 기반으로 재산을 ... 내가 잘못을하고있는 중이 야 무엇을?
Stage
is가 필요 하기 때문에 Stage
관련된 모든 일대 다 관계에는 기본적으로 계단식 삭제가 사용됩니다. Stage
엔터티 를 삭제하면
- 삭제는
Side
- 삭제가 직접 연쇄 것
Card
때문Card
와Side
이 삭제 다시는 그때부터 단계적으로합니다 기본적으로 활성화 계단식으로 일대 다 관계를 필요Card
로Side
그래서, 당신은 두 계단식 삭제 경로가 Stage
에 Side
예외를 발생 -.
Stage
엔티티 중 하나 이상에서 선택 사항을 선택 하거나 ( [Required]
속성에서 속성 제거 Stage
) Fluent API를 사용하여 계단식 삭제를 사용하지 않아야합니다 (데이터 주석으로는 불가능).
modelBuilder.Entity<Card>()
.HasRequired(c => c.Stage)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Side>()
.HasRequired(s => s.Stage)
.WithMany()
.WillCascadeOnDelete(false);
나는 다른 사람들과 순환 관계가있는 테이블을 가지고 있었고 같은 오류가 발생했습니다. 그것은 nullable이 아닌 외래 키에 관한 것입니다. 키가 널 입력 가능하지 않은 경우 관련 오브젝트를 삭제해야하며 순환 관계에서는이를 허용하지 않습니다. 따라서 널 입력 가능 외래 키를 사용하십시오.
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int? StageId { get; set; }
EF 코어에서 어떻게해야할지 궁금한 사람은 :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
..... rest of the code.....
EF7 모델에서 EF6 버전으로 마이그레이션 할 때 많은 엔티티에 대해이 오류가 발생했습니다. 한 번에 하나씩 각 엔티티를 통과하고 싶지는 않았으므로 다음을 사용했습니다.
builder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
builder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
마이그레이션 Up () 메서드에서 cascadeDelete를 false 또는 true로 설정할 수 있습니다. 요구 사항에 따라 다릅니다.
AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false);
나는이 문제도 가지고 있었고 비슷한 스레드 에서이 답변으로 즉시 해결했습니다.
필자의 경우 키 삭제시 종속 레코드를 삭제하고 싶지 않았습니다. 이 상황에서 마이그레이션의 부울 값을 false로 변경하면됩니다.
AddForeignKey("dbo.Stories", "StatusId", "dbo.Status", "StatusID", cascadeDelete: false);
이 컴파일러 오류를 발생시키는 관계를 작성하지만 캐스케이드 삭제를 유지하려는 경우가 있습니다. 당신은 당신의 관계에 문제가 있습니다.
.NET Core에서 onDelete 옵션을 ReferencialAction.NoAction으로 변경했습니다.
constraints: table =>
{
table.PrimaryKey("PK_Schedule", x => x.Id);
table.ForeignKey(
name: "FK_Schedule_Teams_HomeId",
column: x => x.HomeId,
principalTable: "Teams",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
table.ForeignKey(
name: "FK_Schedule_Teams_VisitorId",
column: x => x.VisitorId,
principalTable: "Teams",
principalColumn: "Id",
onDelete: ReferentialAction.NoAction);
});
나는 이것을 고쳤다. 마이그레이션을 추가하면 Up () 메서드에 다음과 같은 줄이 있습니다.
.ForeignKey("dbo.Members", t => t.MemberId, cascadeDelete:True)
일단 cascadeDelete를 삭제하면 작동합니다.
문서화 목적으로, 미래에 온 사람에게이 문제는 이렇게 간단하게 해결 될 수 있으며,이 방법을 사용하면 한 번 비활성화 된 방법을 사용할 수 있으며 일반적으로 방법에 액세스 할 수 있습니다
이 메소드를 컨텍스트 데이터베이스 클래스에 추가하십시오.
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
이상하게 들리지만 이유를 모르겠지만 ConnectionString이 "."를 사용했기 때문에 발생했습니다. "데이터 소스"속성에서. 일단 "localhost"로 변경하면 매력처럼 작동했습니다. 다른 변경은 필요하지 않았습니다.
기존 답변은 훌륭합니다. 다른 이유로 인해이 오류가 발생했다고 덧붙였습니다. 기존 DB에서 초기 EF 마이그레이션을 만들고 싶었지만 -IgnoreChanges 플래그를 사용하지 않고 빈 데이터베이스에 Update-Database 명령을 적용했습니다 (기존의 실패에도 적용).
대신 현재 db 구조가 현재 구조 일 때이 명령을 실행해야했습니다.
Add-Migration Initial -IgnoreChanges
db 구조에 실제 문제가있을 수 있지만 한 번에 한 단계 씩 세계를 구하십시오 ...
에서 .NET 핵심 나는 모든 상위 답변을했다 -하지만 어떤 성공없이. DB 구조를 많이 변경했으며에 대해 새로운 마이그레이션을 시도 할 때마다 update-database
동일한 오류가 발생했습니다.
그런 다음 Package Manager Console에서 예외가 발생할 remove-migration
때까지 하나씩 시작했습니다 .
'20170827183131 _ ***'마이그레이션이 이미 데이터베이스에 적용되었습니다
그 후 새 마이그레이션 ( add-migration
)을 추가 하고 update-database
성공적으로
따라서 내 제안은 다음과 같습니다. 현재 DB 상태가 될 때까지 모든 임시 마이그레이션을 지우십시오.
위에서 언급 한 해결책 중 어느 것도 나를 위해 일하지 않았습니다. 내가해야 할 일은 필요하지 않은 외래 키 (또는 null이 아닌 열 키)에 nullable int (int?)를 사용한 다음 일부 마이그레이션을 삭제하는 것입니다.
마이그레이션을 삭제하여 시작한 다음 nullable int를 시도하십시오.
문제는 수정과 모델 디자인이었습니다. 코드 변경이 필요하지 않았습니다.
간단한 방법은 패키지 관리자 콘솔에서 Update-Database 명령을 할당 한 후 마이그레이션 파일 (cascadeDelete: true)
을 편집 (cascadeDelete: false)
한 다음 마지막 마이그레이션에 문제가있는 경우입니다. 그렇지 않으면 이전 마이그레이션 기록을 확인하고 해당 항목을 복사 한 다음 마지막 마이그레이션 파일에 붙여 넣은 후 동일한 작업을 수행하십시오. 그것은 나를 위해 완벽하게 작동합니다.
'IT' 카테고리의 다른 글
첫 번째 경기 만 잡고 (0) | 2020.03.25 |
---|---|
Dockerfile에서 PATH 환경 변수를 업데이트하는 방법은 무엇입니까? (0) | 2020.03.25 |
Pandas 데이터 프레임의 두 열에 함수를 적용하는 방법 (0) | 2020.03.25 |
Node.JS : 명령 줄을 통해 요청을 통해 또는 직접 호출했는지 감지 (0) | 2020.03.25 |
대기와 수면의 차이점 (0) | 2020.03.25 |