J'ai un problème lorsque j'essaye d'ajouter des contraintes à mes tables. J'obtiens l'erreur:
L'introduction de la contrainte FOREIGN KEY 'FK74988DB24B3C886' sur la table 'Employee' peut provoquer des cycles ou plusieurs chemins en cascade. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d'autres contraintes FOREIGN KEY.
Ma contrainte est entre une Code
table et une employee
table. Le Code
tableau contient Id
, Name
, FriendlyName
, Type
et Value
. Le employee
a un certain nombre de champs qui référencent des codes, de sorte qu'il puisse y avoir une référence pour chaque type de code.
J'ai besoin que les champs soient définis sur null si le code référencé est supprimé.
Des idées comment je peux faire cela?
sql
sql-server
constraints
Ricardo Altamirano
la source
la source
Réponses:
SQL Server fait un simple comptage des chemins en cascade et, plutôt que d'essayer de déterminer si des cycles existent réellement, il suppose le pire et refuse de créer les actions référentielles (CASCADE): vous pouvez et devez toujours créer les contraintes sans les actions référentielles. Si vous ne pouvez pas modifier votre conception (ou si cela compromettrait les choses), vous devriez envisager d'utiliser des déclencheurs en dernier recours.
La résolution des chemins en cascade par FWIW est un problème complexe. D'autres produits SQL ignoreront simplement le problème et vous permettront de créer des cycles, auquel cas ce sera une course pour voir laquelle écrasera la valeur en dernier, probablement à l'ignorance du concepteur (par exemple ACE / Jet fait cela). Je comprends que certains produits SQL tenteront de résoudre des cas simples. Le fait demeure, SQL Server n'essaye même pas, le joue en toute sécurité en interdisant plus d'un chemin et au moins il vous le dit.
Microsoft lui-même conseille l'utilisation de déclencheurs au lieu de contraintes FK.
la source
Une situation typique avec plusieurs chemins en cascade sera la suivante: Une table maître avec deux détails, disons "Master" et "Detail1" et "Detail2". Les deux détails sont supprimés en cascade. Jusqu'à présent, aucun problème. Mais que se passe-t-il si les deux détails ont une relation un-à-plusieurs avec une autre table (dites "SomeOtherTable"). SomeOtherTable a une colonne Detail1ID ET une colonne Detail2ID.
En d'autres termes: certains des enregistrements de SomeOtherTable sont liés aux enregistrements Detail1 et certains des enregistrements de SomeOtherTable sont liés aux enregistrements Detail2. Même s'il est garanti que les enregistrements SomeOtherTable n'appartiennent jamais aux deux détails, il est désormais impossible de supprimer en cascade les enregistrements de SomeOhterTable pour les deux détails, car il existe plusieurs chemins en cascade de Master à SomeOtherTable (un via Detail1 et un via Detail2). Vous l'avez peut-être déjà compris. Voici une solution possible:
Tous les champs d'ID sont des champs de clé et incrémentés automatiquement. Le point crucial réside dans les champs DetailMainId des tables Detail. Ces champs sont à la fois des contraint clés et référentiels. Il est désormais possible de tout supprimer en cascade en supprimant uniquement les fiches. L'inconvénient est que pour chaque enregistrement detail1 ET pour chaque enregistrement detail2, il doit également y avoir un enregistrement DetailMain (qui est en fait créé en premier pour obtenir l'identifiant correct et unique).
la source
Je voudrais souligner que (fonctionnellement) il y a une GRANDE différence entre les cycles et / ou plusieurs chemins dans le SCHEMA et les DATA. Alors que les cycles et peut-être les trajets multiples dans les DONNÉES pourraient certainement compliquer le traitement et causer des problèmes de performances (coût d'une manipulation «correcte»), le coût de ces caractéristiques dans le schéma devrait être proche de zéro.
Étant donné que la plupart des cycles apparents dans les RDB se produisent dans des structures hiérarchiques (organigramme, partie, sous-partie, etc.), il est malheureux que SQL Server suppose le pire; c'est-à-dire, cycle de schéma == cycle de données. En fait, si vous utilisez des contraintes RI, vous ne pouvez pas réellement créer un cycle dans les données!
Je soupçonne que le problème des trajets multiples est similaire; c'est-à-dire que plusieurs chemins dans le schéma n'impliquent pas nécessairement plusieurs chemins dans les données, mais j'ai moins d'expérience avec le problème des trajets multiples.
Bien sûr, si SQL Server l'a fait permet cycles , il serait encore faire l' objet d'une profondeur de 32, mais qui est probablement suffisant pour la plupart des cas. (Dommage que ce ne soit pas un paramètre de base de données cependant!)
Les déclencheurs "au lieu de supprimer" ne fonctionnent pas non plus. La deuxième fois qu'une table est visitée, le déclencheur est ignoré. Donc, si vous voulez vraiment simuler une cascade, vous devrez utiliser des procédures stockées en présence de cycles. Cependant, le déclencheur au lieu de supprimer fonctionnerait pour les cas de trajets multiples.
Celko suggère une «meilleure» façon de représenter les hiérarchies qui n'introduit pas de cycles, mais il y a des compromis.
la source
Il existe un article disponible dans lequel explique comment effectuer plusieurs chemins de suppression à l'aide de déclencheurs. Peut-être que cela est utile pour des scénarios complexes.
http://www.mssqltips.com/sqlservertip/2733/solving-the-sql-server-multiple-cascade-path-issue-with-a-trigger/
la source
Par ses sons, vous avez une action OnDelete / OnUpdate sur l'une de vos clés étrangères existantes, qui modifiera votre table de codes.
Donc, en créant cette clé étrangère, vous créeriez un problème cyclique,
Par exemple, la mise à jour des employés entraîne la modification des codes par une action de mise à jour, la modification des employés par une action de mise à jour ... etc ...
Si vous publiez vos définitions de table pour les deux tables, et vos définitions de clé étrangère / contrainte, nous devrions être en mesure de vous dire où se situe le problème ...
la source
En effet, l'Employyee pourrait avoir la collection d'une autre entité, dire que les qualifications et les qualifications pourraient avoir une autre collection Universités, par exemple
}
}
}
Sur DataContext, cela pourrait être comme ci-dessous
}
dans ce cas, il y a une chaîne de l'employé à la qualification et de la qualification aux universités. Donc ça me faisait la même exception.
Ça a marché pour moi quand j'ai changé
À
la source
Trigger est la solution à ce problème:
la source
Il s'agit d'une erreur de type stratégies de déclenchement de base de données. Un déclencheur est du code et peut ajouter des intelligences ou des conditions à une relation en cascade comme la suppression en cascade. Vous devrez peut-être spécialiser les options de tables associées autour de cela, comme Désactiver CascadeOnDelete :
Ou désactivez complètement cette fonctionnalité:
la source
Ma solution à ce problème rencontré à l'aide d'ASP.NET Core 2.0 et d'EF Core 2.0 consistait à effectuer les opérations suivantes dans l'ordre:
Exécutez la
update-database
commande dans la console de gestion de package (PMC) pour créer la base de données (cela entraîne l'erreur «L'introduction de la contrainte FOREIGN KEY ... peut provoquer des cycles ou plusieurs chemins en cascade.»)Exécutez la
script-migration -Idempotent
commande dans PMC pour créer un script qui peut être exécuté indépendamment des tables / contraintes existantesPrenez le script résultant et recherchez
ON DELETE CASCADE
et remplacez parON DELETE NO ACTION
Exécuter le SQL modifié sur la base de données
Désormais, vos migrations doivent être à jour et les suppressions en cascade ne doivent pas se produire.
Dommage que je n'ai pas pu trouver un moyen de le faire dans Entity Framework Core 2.0.
Bonne chance!
la source