53 votes

Mise à jour de la clé primaire de la valeur à l'aide de entity framework

Je suis en train de mettre à jour une valeur d'un composé de la clé primaire de l'intérieur de l'entity framework et j'obtiens cette erreur: "La propriété" code client " est la partie de l'objet de l'information clé et ne peuvent pas être modifiés. "

Voici mon code:

Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault
customer.CustomerID = "fasdfasdf"
db.SaveChanges()

Il semble trop simple. Est-il vrai que vous ne pouvez pas mettre à jour une clé primaire dans le cadre de l'entité? Je ne trouve pas de documentation sur le sujet. Merci!

62voto

Dr. A Points 451

J'ai un doctor en cs - dans le domaine des Bases de données, de sorte que cette réponse va être un peu différent de celui des programmateurs de point de vue. Avec tout le respect pour Oliver Hanappi, une clé peut et parfois ne change si ce n'est pas une clé de substitution. E. g. Une clé naturelle ou un composit clé. Par exemple. Il est possible d'obtenir votre SSN changé aux états-unis. Mais de nombreux programmeurs années, ne considère pas cela ne change pas la clé et l'utiliser comme tel. Il est beaucoup plus fréquent pour modifier une clé primaire composite constitué de clés étrangères.

Je fais face à une base de données qui a une relation ternaire. Trois entités (avec les clés étrangères étant porteuse des clés primaires dans leurs tables respectives). Toutefois, afin de préserver la relation entre les deux entités tout en changeant la troisième entité nécessite de changer une partie de la table d'intersection (également appelé un pur table de jointure sur MSDN) clé primaire. Ceci est valide et ne peut être améliorée par la suppression de la relation ternaire intersection de la table et en le remplaçant par deux relation binaire tables (qui peuvent avoir leurs propres clés de substitution). EF gère cela très bien. Ce changement de conception qui ferait un (Nombre->nombre)->beaucoup de ou Parent1-Parent2 -> enfant-petit-Enfant modèle (si ce n'est pas évident de lire l'exemple ci-dessous). Entity framework fonctionnerait très bien avec ce que chaque relation est vraiment un un-à-plusieurs relationshiop. Mais c'est un fou de conception à partir d'une base de point de vue. Permettez-moi de vous montrer un exemple de pourquoi.

Considérer que les Cours en Classe, et l'Instructeur sont associés les uns avec les autres dans une classe. Catégorie pourrait inclure: CourseID, ClassroomID, InstructorID comme des clés étrangères et contiennent un composit clé primaire, y compris tous les trois. Bien que d'une façon claire, concise modèle ternaire (3 relation). on peut décomposer en binaire des relations. Ce serait donner de l'intersection de deux tableaux. L'ajout de clés de substitution serait à même de satisfaire EF comme suit:

Catégorie(SurrogateKeyClass, InstructorID, CourseID)

ClassRoomUsed(SurrogateKeyClassroomUsed, SurrogateKeyClass, ClassRoomID)

Le problème avec ce modèle est que nous pourrions avoir le même cours et professeur associé à de multiples reprises, que le précédent modèle évite. Pour éviter ce problème, vous pouvez ajouter une contrainte dans la base de données de l'unicité des deux champs ID, mais pourquoi voudriez-vous faire quand vous ne travailler qu'avec des clés de substitution pour commencer? Cependant, cette solution serait de travailler du mieux que je peux en dire. Ce n'est cependant pas une logique de conception de base de données en raison de la unatural contrainte unique requis dans la base de données.

MAIS, si vous ne voulez pas changer votre base de données ou ne pouvez pas modifier votre base de données, voici un deuxième solution: Intersection/tables d'association sont juste que, des liens qui relient les deux entités ou plus ensemble. Si on change, supprimer l'association et d'en recréer un nouveau qui a les clés étrangères (propriétés de navigation). Cela signifie que vous ne serez pas autorisé à exiger de l'enfant entités dans toutes les relations, mais qui est extrêmement commun.

Je voudrais suggérer que le Cadre de l'Entité (dans le futur) permettre à ceux d'entre nous qui peuvent concevoir un élégant DB modèle de changer des pièces de clés en intersection/tables d'association lorsque nous voulons!

Un autre Exemple est gratuit:

Considérer un Étudiant, Cours, la note de l'Association. Les étudiants sont associés à un cours par l'intermédiaire d'un grade. Habituellement, c'est un de nombreux de nombreux de l'association entre un Élève et un Cours avec un champ supplémentaire dans la table d'association appelée grade (tables d'association ont la charge utile de données comme grade, à l'intersection des tables n'ont pas de charge et sont considérés dans MSDN comme pure tables de jointure au contrat de location en un seul lieu):

Étudiant(StudentID, ....)

Cours(CourseID, ...)

La prise de(StudentID, CourseID, grade)

Si quelqu'un fait une erreur de saisie des données à partir d'une liste déroulante et met un étudiant dans la mauvaise catégorie, vous aimez à le changer plus tard en sélectionnant le menu déroulant de nouveau et en sélectionnant un autre cours. Dans le fond, vous devrez supprimer l'EF objet à partir de la Prise de la table et de le recréer sans perdre une année si, il y en a un. Il suffit de changer de Clé Étrangère CourseID semble être une meilleure alternative. Venir avec votre propre association si celui-ci semble quelque peu exagéré, mais en tant que professeur, il était naturel pour moi.

Conclusion: Lorsque vous avez une chaîne de relations, il peut être préférable de ne pas autoriser en cascade et/ou de modification de FK, mais il existe resonable/logique des scénarios où il est nécessaire, même si c'est pas recommandée comme étant la meilleure pratique en général.

Ce problème peut se manifester avec les Exceptions suivantes, en fonction de si vous modifiez la propriété de navigation ou sur la touche de la propriété dans le modèle, respectivement:

Une contrainte d'intégrité référentielle violation s'est produite: Une propriété de clé primaire qui est une partie de la contrainte d'intégrité référentielle ne peut pas être modifié lorsque l'objet dépendant est Inchangé, sauf si elle est définie à l'association de l'objet principal. L'objet principal doivent être suivis et qui ne sont pas marqués pour suppression.

La propriété " X " est la partie de l'objet de l'information clé et ne peuvent pas être modifiés.

23voto

Shiraz Bhaiji Points 34901

Vous ne pouvez pas mettre à jour la clé primaire via entity framework, depuis entity framework ne sais pas qui ligne de base de données à mise à jour.

Toutefois, si vous avez vraiment besoin de le faire, vous pourriez écrire une procédure stockée que les mises à jour de la clé primaire, puis exécutez la procédure stockée à partir d'entity framework.

9voto

Nathan W Points 19990

Vous ne pouvez pas et pour une bonne raison. Voir KM de commentaires.

Une chose que je dis que vous pourriez faire est d'avoir deux tables, l'une avec des données anonymes et qui stocke le réel de données de l'utilisateur après l'ouverture de la session.

Ou vous pouvez (pas testé ou jamais fait par moi) c'est d'avoir ce genre de disposition de table:

---Customers----
AutoNumber PK <- This links to all other tables in your database, and does NOT change.
CustomerID  <- This can change.
CustomerType <- Anonymous or logged in.

Et quand ils se connectent, vous modifiez la CustomerType et CustomerID à ce que vous avez besoin.

Afin que votre requête pourrait ressembler à ceci:

Dim customer As Customer = (From c In db.Customer _
                            Where c.CustomerID = {Some temp ID} _
                            AndAlso c. CustomerType = "Anonymous").FirstOrDefault
// After user logs in.
customer.CustomerID = {Make a new user ID here}
customer.CustomerType = "LoggedIn" {or what ever}
db.SaveChanges()

Noter que la numérotation automatique de la clé primaire ne jamais les changements. C'est alors que toutes les tables qui sont dans une relation avec les Clients, table de travail et ne pas avoir à faire de mises à jour en cascade sur la clé primaire (qui est, comme vous-même coup de poignard dans l'oeil avec un crayon).

-4voto

Oliver Hanappi Points 5141

Vous ne pouvez pas mettre à jour une clé primaire, mais ce n'est pas une limitation de l'entity framework, mais à une règle fondamentale de développement de base de données. Une clé primaire est attribué à la fois à une ligne dans une table et fait de cette ligne unique.
Peut-être que vous pouvez mettre à jour la clé, à certains égards, mais cela viole certainement la définition d'une clé primaire.

Donc, il suffit de ne pas le faire, il y a d'autres façons d'accomplir ce que vous essayez de faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X