Actualizar el valor de la clave principal utilizando el marco de la entidad

Estoy tratando de actualizar un valor de una clave primaria compuesta dentro del marco de la entidad y recibo este error: “La propiedad ‘CustomerID’ es parte de la información clave del objeto y no se puede modificar”.

Aquí está mi código:

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

Parece muy simple. ¿Es cierto que no puede actualizar una clave principal dentro del marco de la entidad? No puedo encontrar ninguna documentación sobre el tema. ¡Gracias!

No puedes y por una buena razón. Ver los comentarios de KM.

Una cosa que digo que podría hacer es tener dos tablas, una con datos anónimos y otra que almacene los datos reales del usuario después de iniciar sesión.

O tu podrías (no probado o hecho por mí) tener este tipo de diseño de mesa:

 ---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. 

Y cuando inician sesión cambias el CustomerType y el CustomerID a lo que necesitas.

Entonces su consulta podría verse así:

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

Tenga en cuenta que la clave primaria del autonumber nunca cambia. Esto es para que todas las tablas que tenga en una relación con la tabla Customers sigan funcionando y no tenga que hacer actualizaciones en cascada en la clave principal (que es como apuñalarse en el ojo con un lápiz).

Tengo un Ph.D. en cs: en el área de Bases de datos, esta respuesta será un poco diferente de la perspectiva de los progtwigdores. Con todo respeto a Oliver Hanappi, una clave puede cambiar ocasionalmente si no es una clave sustituta. Por ejemplo, una clave natural o una clave compuesta. Por ejemplo. Es posible obtener su SSN cambiado en los Estados Unidos. Pero muchos progtwigdores a lo largo de los años considerarían esta clave como inmutable y la usarían como tal. Es mucho más común cambiar una clave primaria compuesta compuesta por claves externas.

Estoy tratando con una base de datos que tiene una relación ternaria. Específicamente tres entidades (con claves externas que son claves primarias sustitutas en sus tablas respectivas). Sin embargo, para preservar la relación entre dos entidades al cambiar la tercera entidad, es necesario cambiar parte de la tabla principal de la tabla de intersección (también llamada tabla de unión pura en MSDN). Este es un diseño válido y solo podría mejorarse eliminando la tabla de intersecciones de relaciones ternarias y reemplazándola con dos tablas de relaciones binarias (que pueden tener sus propias claves sustitutas). EF manejaría esto bien. Este cambio de diseño haría un modelo (Muchos-> Muchos) -> Muchos o Padres1-Padres2-> Hijo-nieto (si no está claro, lea el ejemplo a continuación). El marco de la entidad funcionaría bien con esto ya que cada relación es realmente una relación de uno a muchos. Pero es un diseño loco desde una perspectiva DB. Déjame mostrarte un ejemplo de por qué.

Considere que Course, Classroom e Instructor están asociados entre sí en una clase. La clase podría incluir: CourseID, ClassroomID, InstructorID como claves foráneas y contener una clave primaria compuesta que incluya las tres. Aunque es un modelo ternario claro y conciso (relación de 3 vías) podríamos dividirlo en relaciones binarias. Esto daría dos tablas de intersección. Agregar claves sustitutas satisfaría a EF de la siguiente manera:

Clase ( SurrogateKeyClass , InstructorID , CourseID )

ClassRoomUsed ( SurrogateKeyClassroomUsed , SurrogateKeyClass , ClassRoomID )

El problema con este diseño es que podríamos tener el mismo curso e instructor asociado varias veces, lo que el modelo anterior evita. Para evitar este problema, puede agregar una restricción en la base de datos para la unicidad de los dos campos ID, pero ¿por qué querría hacer esto cuando solo está tratando con claves sustitutas para empezar? Sin embargo, esta solución funcionaría lo mejor que puedo decir. Sin embargo, este no es un diseño de base de datos lógica debido a la restricción única no natural requerida en el DB.

PERO, si no quiere cambiar su base de datos o no puede cambiar su base de datos, aquí hay una segunda solución : las tablas de intersección / asociación son solo eso, enlaces que unen dos o más entidades. Si uno cambia, elimine la asociación y vuelva a crear una nueva que tenga las claves externas apropiadas (propiedades de navegación). Eso significa que no se le permitirá requerir entidades secundarias en ninguna de las relaciones, pero eso es extremadamente común.

¡Sugeriría que el Entity Framework (en el futuro) nos permita a aquellos de nosotros que podemos diseñar un elegante modelo de DB cambiar partes de claves en tablas de intersección / asociación cuando queramos!

Otro ejemplo gratis:

Considere un Estudiante, Curso, Asociación de Grado. Los estudiantes están asociados con un curso por un grado. Por lo general, esta es una asociación muchos a muchos entre Estudiante y un Curso con un campo adicional en la tabla de asociación llamado grado (las tablas de asociación tienen datos de carga útil como grado, las tablas de intersección no tienen una carga útil y se hace referencia en MSDN como tablas de unión pura en arrendamiento en un lugar):

Estudiante ( StudentID , ….)

Curso ( CourseID , …)

Tomando ( StudentID , CourseID , grado)

Si alguien hace un error de ingreso de datos de un menú desplegable y coloca a un alumno en la clase incorrecta, le agrada que lo cambie más adelante seleccionando el menú desplegable de nuevo y seleccionando un curso diferente. En el fondo, tendrá que eliminar el objeto EF de la tabla Toma y volver a crearlo sin perder una calificación, si es que hay una. Simplemente cambiando el Foreign Key CourseID parece una mejor alternativa. Propón tu propia asociación si esta parece artificial, pero como profesor fue natural para mí.

Conclusión: cuando tiene una cadena de relaciones, puede ser mejor no permitir la conexión en cascada y / o cambiar FK, pero existen escenarios razonables / lógicos donde se necesita, incluso si no se recomienda como una mejor práctica en general .

Este problema puede manifestarse con las siguientes Excepciones dependiendo de si está cambiando la propiedad de navegación o la propiedad clave en el modelo, respectivamente:

Ocurrió una violación de restricción de integridad referencial: una propiedad de clave primaria que es parte de la restricción de integridad referencial no se puede cambiar cuando el objeto dependiente está Sin cambios a menos que se establezca en el objeto principal de la asociación. El objeto principal debe rastrearse y no marcarse para su eliminación.

La propiedad ‘X’ es parte de la información clave del objeto y no se puede modificar.

No puede actualizar la clave primaria a través del marco de la entidad, ya que el marco de la entidad no sabría qué fila de la base de datos actualizar.

Sin embargo, si realmente necesita hacerlo, podría escribir un procedimiento almacenado que actualice la clave principal, y luego ejecutar el procedimiento almacenado desde el marco de la entidad.

No puede actualizar una clave principal, pero eso no es una limitación del marco de la entidad, sino una regla fundamental para el desarrollo de la base de datos. Una clave principal se asigna una vez a una fila en una tabla y hace que esta fila sea única.
Tal vez pueda actualizar la clave de alguna manera, pero esto viola definitivamente la definición de una clave principal.

Entonces, simplemente no lo hagas, hay otras formas de lograr lo que estás tratando de hacer.