Tenho um problema ao tentar adicionar restrições às minhas tabelas. Eu recebo o erro:
A introdução da restrição FOREIGN KEY 'FK74988DB24B3C886' na tabela 'Funcionário' 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.
Minha restrição é entre uma Code
mesa e uma employee
mesa. A Code
tabela contém Id
, Name
, FriendlyName
, Type
e Value
. O employee
possui um número de campos que referenciam códigos, para que possa haver uma referência para cada tipo de código.
Eu preciso que os campos sejam definidos como nulos se o código referenciado for excluído.
Alguma idéia de como posso fazer isso?
sql
sql-server
constraints
Ricardo Altamirano
fonte
fonte
Respostas:
O SQL Server faz uma contagem simples de caminhos em cascata e, em vez de tentar descobrir se existe algum ciclo, assume o pior e se recusa a criar as ações referenciais (CASCADE): você pode e ainda deve criar as restrições sem as ações referenciais. Se você não pode alterar seu design (ou isso comprometeria as coisas), considere o uso de gatilhos como último recurso.
A resolução de caminhos em cascata do FWIW é um problema complexo. Outros produtos SQL simplesmente ignoram o problema e permitem criar ciclos. Nesse caso, será uma corrida para ver quem substituirá o valor por último, provavelmente por ignorância do designer (por exemplo, o ACE / Jet faz isso). Entendo que alguns produtos SQL tentarão resolver casos simples. Fato permanece: o SQL Server nem tenta, o reproduz de maneira ultra segura ao proibir mais de um caminho e, pelo menos, diz isso.
A própria Microsoft aconselha o uso de gatilhos em vez de restrições de FK.
fonte
Uma situação típica com vários caminhos de cascasing será a seguinte: Uma tabela mestre com dois detalhes, digamos "Mestre" e "Detalhe1" e "Detalhe2". Ambos os detalhes são exclusão em cascata. Até agora sem problemas. Mas e se os dois detalhes tiverem uma relação um-para-muitos com alguma outra tabela (diga "SomeOtherTable"). SomeOtherTable possui uma coluna Detail1ID E uma coluna Detail2ID.
Em outras palavras: alguns dos registros em SomeOtherTable estão vinculados aos registros Detail1 e alguns dos registros em SomeOtherTable estão vinculados aos registros Detail2. Mesmo que seja garantido que SomeOtherTable-records nunca pertençam a ambos os Detalhes, agora é impossível fazer com que os registros de SomeOhterTable sejam excluídos em cascata dos dois detalhes, porque existem vários caminhos em cascata do Master para SomeOtherTable (um via Detail1 e outro via Detail2). Agora você já deve ter entendido isso. Aqui está uma solução possível:
Todos os campos de ID são campos-chave e incremento automático. O ponto crucial está nos campos DetailMainId das tabelas Detail. Esses campos são chave e referência referencial. Agora é possível excluir tudo em cascata excluindo apenas registros mestre. A desvantagem é que, para cada registro detail1 E para cada registro detail2, também deve haver um registro DetailMain (que é realmente criado primeiro para obter a identificação correta e exclusiva).
fonte
Eu apontaria que (funcionalmente) há uma GRANDE diferença entre ciclos e / ou caminhos múltiplos no SCHEMA e nos DATA. Embora os ciclos e talvez os caminhos múltiplos nos DATA certamente possam complicar o processamento e causar problemas de desempenho (custo de manuseio "adequado"), o custo dessas características no esquema deve ser próximo de zero.
Como a maioria dos ciclos aparentes nos RDBs ocorre em estruturas hierárquicas (organograma, parte, subparte etc.), é lamentável que o SQL Server assuma o pior; ou seja, ciclo de esquema == ciclo de dados. De fato, se você estiver usando restrições de RI, não poderá criar um ciclo nos dados!
Suspeito que o problema de caminhos múltiplos seja semelhante; ou seja, vários caminhos no esquema não implicam necessariamente vários caminhos nos dados, mas tenho menos experiência com o problema de caminhos múltiplos.
Claro, se SQL Server que permitem ciclos que ainda estaria sujeita a uma profundidade de 32, mas isso é provavelmente adequado para a maioria dos casos. (Pena que não é uma configuração de banco de dados!)
Os gatilhos "Em vez de excluir" também não funcionam. Na segunda vez que uma tabela é visitada, o gatilho é ignorado. Portanto, se você realmente deseja simular uma cascata, precisará usar procedimentos armazenados na presença de ciclos. No entanto, o gatilho Em vez de excluir excluir funcionaria para casos de caminhos múltiplos.
Celko sugere uma maneira "melhor" de representar hierarquias que não introduzem ciclos, mas existem compensações.
fonte
Existe um artigo disponível no qual explica como executar vários caminhos de exclusão usando gatilhos. Talvez isso seja útil para cenários complexos.
http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/
fonte
Pelo que parece, você tem uma ação OnDelete / OnUpdate em uma de suas chaves estrangeiras existentes, que modificará sua tabela de códigos.
Então, ao criar essa chave estrangeira, você criaria um problema cíclico,
Por exemplo, a atualização de funcionários, faz com que os códigos sejam alterados por uma ação na atualização, faz com que os funcionários sejam alterados por uma ação na atualização ... etc ...
Se você publicar suas Definições de tabela para ambas as tabelas e suas definições de chave estrangeira / restrição, poderemos informar onde está o problema ...
fonte
Isso ocorre porque o Emplyee pode ter Coleção de outra entidade, digamos, Qualificações e Qualificação podem ter outras coleções.
}
}
}
No DataContext, pode ser como abaixo
}
nesse caso, existe uma cadeia de funcionário para qualificação e de qualificação para universidades. Então estava lançando a mesma exceção para mim.
Funcionou para mim quando mudei
Para
fonte
O gatilho é a solução para este problema:
fonte
Este é um erro do tipo políticas de gatilho de banco de dados. Um gatilho é um código e pode adicionar algumas inteligências ou condições a uma relação em cascata, como exclusão em cascata. Pode ser necessário especializar as opções de tabelas relacionadas, como Desativar o CascadeOnDelete :
Ou desative esse recurso completamente:
fonte
Minha solução para esse problema encontrada usando o ASP.NET Core 2.0 e o EF Core 2.0 foi executar o seguinte na ordem:
Execute o
update-database
comando no Package Management Console (PMC) para criar o banco de dados (isso resulta no erro "Introdução à restrição FOREIGN KEY ... pode causar ciclos ou vários caminhos em cascata".)Executar
script-migration -Idempotent
comando no PMC para criar um script que possa ser executado independentemente das tabelas / restrições existentesPegue o script resultante e encontre
ON DELETE CASCADE
e substitua porON DELETE NO ACTION
Execute o SQL modificado no banco de dados
Agora, suas migrações devem estar atualizadas e as exclusões em cascata não devem ocorrer.
Pena que não consegui encontrar nenhuma maneira de fazer isso no Entity Framework Core 2.0.
Boa sorte!
fonte