Estou lutando com isso há um tempo e não consigo entender o que está acontecendo. Eu tenho uma entidade de cartão que contém lados (geralmente 2) - e ambos os cartões e lados têm um estágio. Estou usando as migrações EF Codefirst e as migrações estão falhando com este erro:
A introdução da restrição FOREIGN KEY 'FK_dbo.Sides_dbo.Cards_CardId' na tabela 'Lados' pode causar ciclos ou vários caminhos em cascata. Especifique ON DELETE NO ACTION ou ON UPDATE NO ACTION ou modifique outras restrições de FOREIGN KEY.
Aqui está a entidade do meu cartão :
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; }
}
Aqui está minha entidade Side :
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; }
}
E aqui está minha entidade Stage :
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; } }
}
O que é estranho é que se eu adicionar o seguinte à minha classe Stage:
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
A migração é executada com sucesso. Se eu abrir o SSMS e olhar para as tabelas, posso ver que Stage_StageId
foi adicionado a Cards
(como esperado / desejado), mas Sides
não contém nenhuma referência a Stage
(não esperado).
Se eu adicionar
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
Na minha classe Side, vejo a StageId
coluna adicionada à minha Side
tabela.
Isso está funcionando, mas agora, em toda a minha aplicação, qualquer referência a Stage
contém a SideId
, que em alguns casos é totalmente irrelevante. Eu gostaria de apenas dar às minhas entidades Card
e Side
uma Stage
propriedade com base na classe Stage acima sem poluir a classe stage com propriedades de referência, se possível ... o que estou fazendo de errado?
Side
Class, inclua número inteiro nulo e remova o[Required]
atributo =>public int? CardId { get; set; }
DeleteBehavior.Restrict
ouDeleteBehavior.SetNull
.Respostas:
Como
Stage
é necessário , todos os relacionamentos um para muitosStage
envolvidos estão com a exclusão em cascata ativada por padrão. Isso significa que, se você excluir umStage
entidadeSide
Card
e porque,Card
eSide
terá um relacionamento um-para-muitos necessário com a exclusão em cascata ativada por padrão novamente, ela será cascateada deCard
paraSide
Portanto, você tem dois caminhos de exclusão em cascata de
Stage
paraSide
- o que causa a exceção.Você deve tornar o
Stage
opcional em pelo menos uma das entidades (por exemplo, remover o[Required]
atributo dasStage
propriedades) ou desativar a exclusão em cascata com a API Fluent (não é possível com anotações de dados):fonte
Stage
. Outros relacionamentos permanecem inalterados.Stage
deleção em cascata para baixo paraSide
tanto directamente como através de umCard
Eu tinha uma tabela que tinha um relacionamento circular com os outros e estava recebendo o mesmo erro. Acontece que é sobre a chave estrangeira que não foi anulável. Se a chave não for anulável, o objeto relacionado deve ser excluído e as relações circulares não permitem isso. Portanto, use chave estrangeira anulável.
fonte
int?
vez deint
deixá-la anulável.Alguém quer saber como fazer isso no núcleo da EF:
fonte
builder.HasOne(x => x.Stage).WithMany().HasForeignKey(x => x.StageId).OnDelete(DeleteBehavior.Restrict);
builder _ .Entity<TEntity>() _
anteriorHasOne()
pode ser chamado ...IEntityTypeConfiguration<T>
. Não me lembro de ter visto obuilder.Entity<T>
método naqueles dias, mas posso estar errado. No entanto, os dois vão trabalhar :)Eu estava recebendo esse erro para muitas entidades quando estava migrando de um modelo EF7 para uma versão EF6. Como não queria passar por cada entidade, uma de cada vez, usei:
fonte
Você pode definir cascadeDelete como false ou true (no método Up () de migração). Depende de sua exigência.
fonte
UP
método pode ser modificado por operações externas.No .NET Core, alterei a opção onDelete para ReferencialAction.NoAction
fonte
Eu também tive esse problema, resolvi-o instantaneamente com esta resposta de um tópico semelhante
No meu caso, não quis excluir o registro dependente na exclusão da chave. Se este for o seu caso, basta alterar o valor booleano na migração para false:
As chances são de que, se você estiver criando relacionamentos que geram esse erro do compilador, mas desejam manter a exclusão em cascata; você tem um problema com seus relacionamentos.
fonte
Eu consertei isso. Quando você adiciona a migração, no método Up () haverá uma linha como esta:
Se você apenas excluir o cascadeDelete do final, ele funcionará.
fonte
Apenas para fins de documentação, para alguém que vem no futuro, isso pode ser resolvido de maneira simples e, com esse método, você pode executar um método que desativou uma vez e acessar seu método normalmente.
Adicione este método à classe de banco de dados de contexto:
fonte
Isso parece estranho e não sei por que, mas no meu caso isso estava acontecendo porque meu ConnectionString estava usando "." no atributo "fonte de dados". Depois que eu mudei para "localhost", funcionou como um encanto. Nenhuma outra mudança foi necessária.
fonte
No .NET Core, eu brinquei com todas as respostas superiores - mas sem sucesso. Fiz muitas alterações na estrutura do banco de dados e sempre adicionava nova migração tentando
update-database
, mas recebia o mesmo erro.Então comecei
remove-migration
um por um até o Console do Gerenciador de Pacotes me lançar uma exceção:Depois disso, adicionei nova migração (
add-migration
) eupdate-database
obtive sucessoPortanto, minha sugestão seria: limpar todas as suas migrações temporárias, até o estado atual do banco de dados.
fonte
As respostas existentes são ótimas. Só queria acrescentar que encontrei esse erro por um motivo diferente. Eu queria criar uma migração EF inicial em um banco de dados existente, mas não usei o -IgnoreChanges sinalizador e apliquei o comando Update-Database em um banco de dados vazio (também nas falhas existentes).
Em vez disso, tive que executar este comando quando a estrutura db atual é a atual:
Provavelmente, existe um problema real na estrutura do banco de dados, mas salve o mundo um passo de cada vez ...
fonte
A maneira mais simples é, Editar seu arquivo de migração
(cascadeDelete: true)
em(cascadeDelete: false)
seguida, depois de atribuir o comando Update-banco de dados no seu Gerenciador de Pacotes Console.if-lo do problema com a sua última migração então tudo bem. Caso contrário, verifique seu histórico de migração anterior, copie essas coisas, cole no seu último arquivo de migração e depois faça o mesmo. funciona perfeitamente para mim.fonte
Quando sua migração falha, você recebe algumas opções: 'Introdução à restrição FOREIGN KEY' FK_dbo.RecommendedBook_dbo.Department_DepartmentID 'na tabela' RecommendedBook 'pode causar ciclos ou vários caminhos em cascata. Especifique ON DELETE NO ACTION ou ON UPDATE NO ACTION ou modifique outras restrições de FOREIGN KEY. Não foi possível criar restrição ou índice. Veja erros anteriores.
Aqui está um exemplo do uso de 'modificar outras restrições FOREIGN KEY', configurando 'cascadeDelete' como false no arquivo de migração e, em seguida, execute 'update-database'.
fonte
Nenhuma das soluções mencionadas funcionou para mim. O que eu tive que fazer foi usar um int nulo (int?) Na chave estrangeira que não era necessária (ou não uma chave de coluna não nula) e, em seguida, excluir algumas das minhas migrações.
Comece excluindo as migrações e tente o int nulo.
O problema era tanto uma modificação quanto um design de modelo. Nenhuma alteração de código foi necessária.
fonte
Torne seus atributos de chave estrangeira anuláveis. Isso vai funcionar.
fonte