2012-04-19 11 views
7

Tengo una restricción única en una columna de la tabla Navigations llamada Index. Tengo dos entidades Navigation y quiero cambiar sus valores Index.Intercambio de valores con una restricción única en Entity Framework

Cuando llamo al db.SaveChanges arroja una excepción que indica que se ha violado una restricción única. Parece que EF está actualizando un valor y luego el otro, violando así la restricción.

¿No debería estar actualizando ambos en una transacción y luego tratando de comprometer una vez que los valores están ordenados y no en violación de la restricción?

¿Hay alguna forma de evitar esto sin usar valores temporales?

+1

¿Podría mostrar algún código? – Likurg

+0

necesita valores de temperatura aquí, una actualización es una operación independiente. por lo que siempre obtendrá una violación de restricción, la única otra opción es deshabilitar las restricciones para la operación. –

Respuesta

9

No es un problema de EF sino del problema de la base de datos SQL porque los comandos de actualización se ejecutan secuencialmente. La transacción no tiene nada que ver con esto: todas las restricciones se validan por comando, no por transacción. Si desea intercambiar valores únicos, necesita más pasos en los que utilizará valores ficticios adicionales para evitar esta situación.

+0

Esto parece peligroso debido a la posibilidad de que surjan problemas con solicitudes simultáneas que utilizan el mismo valor ficticio, o quizás un valor ficticio que también infringe la restricción. ¿Hay una "mejor práctica" para esta situación que usted conozca? –

+1

También puede eliminar registros antiguos y crear nuevos. Intentaré evitar esto en primer lugar.Es una situación en la que la restricción única no se ajusta a las necesidades de la lógica de la aplicación. –

+0

Bastante justo. Voy a eliminar la restricción única de la base de datos. No causará ningún problema si hay duplicados. Si los hay, estarán en un orden poco fiable cuando se muestren en una barra de navegación. –

2

Se puede ejecutar una consulta SQL personalizada para cambiar los valores, así:

update Navigation 
set valuecolumn = 
     case 
      when id=1 then 'value2' 
      when id=2 then 'value1' 
     end 
where id in (1,2) 

Sin embargo, Entity Framework no se puede hacer eso, porque es fuera del alcance de un ORM. Simplemente ejecuta declaraciones secuenciales update para cada entidad alterada, como describió Ladislav en su respuesta.

Otra posibilidad sería soltar la restricción UNIQUE en su base de datos y confiar en la aplicación para aplicar esta restricción correctamente. En este caso, EF podría guardar los cambios muy bien, pero dependiendo de su escenario, puede que no sea posible.

3

Hay algunos enfoques. Algunos de ellos están cubiertos en otras respuestas y comentarios, pero para completarlos, los enumeraré aquí (tenga en cuenta que esta es solo una lista que hice una lluvia de ideas y que podría no ser tan completa).

  1. Realiza todas las actualizaciones en un solo comando. Ver W0lf's answer para ver un ejemplo de esto.
  2. Haga dos conjuntos de actualizaciones: una para intercambiar todos los valores al negativo del valor deseado y luego un segundo para cambiarlos de negativo a positivo. Esto está trabajando en las suposiciones de que los valores negativos no son prevenidos por otras restricciones y que no son valores que tendrán registros que no sean aquellos en un estado transitorio.
  3. Agregue una columna adicional - IsUpdating por ejemplo - establézcalo en verdadero en el primer conjunto de actualizaciones donde se cambian los valores y luego configúrelo de nuevo en falso en un segundo conjunto de actualizaciones. Cambie la restricción única para un índice único filtrado que ignora los registros donde IsUpdating es verdadero.
  4. Elimina la restricción y trata los valores duplicados.
+0

La idea de configurar a negativo y luego a positivo fue inteligente y me sirvió de algo. ¡Gracias! – jslatts

Cuestiones relacionadas