Mettre à jour la valeur de la clé primaire à l'aide du cadre de l'entité

.net entity-framework sql-server vb.net

Question

J'essaie de mettre à jour une valeur d'une clé primaire composée à partir du cadre de l'entité et j'obtiens cette erreur: "La propriété 'CustomerID' fait partie des informations de clé de l'objet et ne peut pas être modifiée."

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()

Cela 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 aucune documentation sur le sujet. Merci!

Réponse acceptée

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

Une chose que je dis que vous pourriez faire est d’avoir deux tables, l’une avec des données anonymes et l’autre qui stocke les données réelles des utilisateurs après leur connexion.

Ou bien vous pourriez (non testé ou jamais fait par moi) avoir ce genre de tableau:

---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 lorsqu'ils se connectent, vous modifiez le CustomerType et le CustomerID en fonction de vos besoins.

Donc, 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()

Notez que la clé primaire de numérotation automatique ne change jamais . Ainsi, toutes les tables que vous entretenez dans une relation avec la table Customers fonctionnent toujours et n'ont pas à effectuer de mises à jour en cascade sur la clé primaire (ce qui revient à se poignarder l'œil avec un crayon).


Réponse populaire

J'ai un doctorat dans cs - dans le domaine des bases de données, cette réponse sera donc légèrement différente de celle des programmeurs. En tout respect pour Oliver Hanappi, une clé peut et est parfois modifiée si ce n'est pas une clé de substitution. Par exemple, une clé naturelle ou une clé composite. Par exemple. Il est possible de changer votre SSN aux États-Unis. Mais de nombreux programmeurs au cours des années ont considéré que cette clé était immuable et l’utilisaient comme telle. Il est beaucoup plus courant de modifier une clé primaire composite composée de clés étrangères.

Je traite avec une base de données qui a une relation ternaire. Plus précisément, trois entités (les clés étrangères étant des clés primaires de substitution dans leurs tables respectives). Cependant, pour préserver la relation entre deux entités lors de la modification de la troisième entité, il est nécessaire de modifier une partie de la table primaire de la table d'intersection (également appelée table de jointure pure sur MSDN). Cette conception est valide et ne peut être améliorée qu'en supprimant la table d'intersection des relations ternaires et en la remplaçant par deux tables de relations binaires (qui peuvent avoir leurs propres clés de substitution). EF s'occuperait de cette amende. Cette modification de conception créerait un modèle (Plusieurs-> Plusieurs) -> Plusieurs ou Parent1-Parent2 -> Enfant-petit-enfant (si ce n'est pas clair, lisez l'exemple ci-dessous). Le cadre d'entité fonctionnerait bien avec ceci car chaque relation est vraiment une relation un à plusieurs. Mais c'est un design fou du point de vue de la base de données. Laissez-moi vous montrer un exemple pourquoi.

Considérez que cours, salle de classe et instructeur sont associés l'un à l'autre dans un cours. La classe peut inclure: CourseID, ClassroomID, InstructorID en tant que clés étrangères et contient une clé primaire composite comprenant les trois. Bien que le modèle ternaire soit clair et concis (relation à trois), nous pourrions le diviser en relations binaires. Cela donnerait deux tables d'intersection. Ajouter des clés de substitution satisferait EF comme suit:

Classe ( SurrogateKeyClass , InstructorID , CourseID )

ClassRoomUsed ( SurrogateKeyClassroomUsed , SurrogateKeyClass , ClassRoomID )

Le problème avec cette conception est que nous pourrions avoir le même cours et le même instructeur associés plusieurs fois, ce que le modèle précédent évite. Pour éviter ce problème, vous pouvez ajouter une contrainte dans la base de données pour l'unicité des deux champs d'ID, mais pourquoi voudriez-vous le faire alors que vous utilisez uniquement des clés de substitution? Cependant, cette solution fonctionnerait du mieux que je peux dire. Toutefois, il ne s'agit pas d'une conception de base de données logique en raison de la contrainte unique et non naturelle requise dans la base de données.

MAIS, si vous ne souhaitez pas modifier votre base de données ou si vous ne pouvez pas le faire, voici une seconde solution : les tables d’intersection / association ne sont que cela, des liens reliant deux entités ou plus. Si vous en modifiez une, supprimez l'association et recréez-en une nouvelle avec les clés étrangères appropriées (propriétés de navigation). Cela signifie que vous ne serez pas autorisé à exiger des entités enfants dans les relations, mais cela est extrêmement courant.

Je suggérerais qu'Entity Framework (à l'avenir) permette à ceux d'entre nous qui peuvent concevoir un modèle de base de données élégant de modifier des parties de clés dans des tables d'intersection / association quand on le souhaite!

Un autre exemple gratuit:

Considérons un étudiant, un cours, une association de notes. Les étudiants sont associés à un cours via une note. Il s'agit généralement d'une association multiple entre étudiant et cours comportant un champ supplémentaire dans la table d'association appelé grade (les tables d'association contiennent des données de charge utile telles que le niveau, les tables d'intersection n'ont pas de charge utile et sont référencées dans MSDN comme des tables de jointure pures louer à un endroit):

Étudiant ( StudentID , ....)

Cours ( CourseID , ...)

Prendre ( StudentID , CourseID , grade)

Si quelqu'un commet une erreur de saisie de données dans une liste déroulante et place un élève dans la mauvaise classe, vous voudrez bien la modifier ultérieurement en sélectionnant à nouveau la liste déroulante, puis en sélectionnant un autre cours. En arrière-plan, vous devrez supprimer l'objet EF de la table Taking et le recréer sans perdre de note s'il en existe une. Changer simplement la clé étrangère CourseID semble être une meilleure alternative. Créez votre propre association si celle-ci semble artificielle, mais en tant que professeur, c'était naturel pour moi.

Conclusion: lorsque vous avez une chaîne de relations, il peut être préférable de ne pas autoriser la mise en cascade et / ou la modification de FK, mais il existe des scénarios logiques / résonables où cela est nécessaire, même si cela n'est pas recommandé en tant que meilleure pratique en général .

Ce problème peut se manifester avec les exceptions suivantes, selon que vous modifiez la propriété de navigation ou la propriété de clé dans le modèle, respectivement:

Une violation de contrainte d'intégrité référentielle s'est produite: une propriété de clé primaire faisant partie de la contrainte d'intégrité référentielle ne peut pas être modifiée lorsque l'objet dépendant est Inchangé à moins d'être défini sur l'objet principal de l'association. L'objet principal doit être suivi et non marqué pour suppression.

La propriété 'X' fait partie des informations clés de l'objet et ne peut pas être modifiée.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow