La mejor forma de guardar una lista ordenada en la base de datos mientras se mantiene el orden

Me preguntaba si alguien tiene una buena solución para un problema que he encontrado en numerosas ocasiones durante los últimos años.

Tengo un carrito de compras y mi cliente solicita explícitamente que el pedido sea significativo. Entonces necesito persistir el pedido al DB.

La forma más obvia sería simplemente insertar un campo de órdenes donde asignaría el número 0 a N y ordenarlo de esa manera.

Pero hacerlo dificultaría más el reordenamiento y, de alguna manera, creo que esta solución es algo frágil y volverá a surgir algún día.

(Uso C # 3,5 con NHibernate y SQL Server 2005)

Gracias

FWIW, creo que la forma en que sugieres (es decir, el envío de la orden a la base de datos) no es una mala solución para tu problema. También creo que es probablemente la forma más segura / más confiable.

Bien, aquí está mi solución para hacer que la progtwigción sea más fácil para cualquiera que pase por este hilo. el truco está en poder actualizar todos los índices de orden por encima o por debajo de una inserción / eliminación en una actualización.

Usar una columna numérica (entera) en su tabla, respaldada por las consultas SQL

CREATE TABLE myitems (Myitem TEXT, id INTEGER PRIMARY KEY, orderindex NUMERIC); 

Para eliminar el artículo en orderindex 6:

 DELETE FROM myitems WHERE orderindex=6; UPDATE myitems SET orderindex = (orderindex - 1) WHERE orderindex > 6; 

Para intercambiar dos elementos (4 y 7):

 UPDATE myitems SET orderindex = 0 WHERE orderindex = 4; UPDATE myitems SET orderindex = 4 WHERE orderindex = 7; UPDATE myitems SET orderindex = 7 WHERE orderindex = 0; 

es decir, 0 no se usa, por lo tanto, utilice un a como un maniquí para evitar tener un artículo ambiguo.

Para insertar en 3:

  UPDATE myitems SET orderindex = (orderindex + 1) WHERE orderindex > 2; INSERT INTO myitems (Myitem,orderindex) values ("MytxtitemHere",3) 

La mejor solución es una lista doblemente enlazada . O (1) para todas las operaciones excepto la indexación. Nada puede indexar SQL rápidamente, excepto una cláusula where en el elemento que desee.

0,10,20 tipos fallan Los de la columna de secuencia fallan. La columna de secuencia flotante falla en movimientos de grupo.

La lista doblemente enlazada es la misma operación para agregar, eliminar, eliminar grupo, agregar grupo, mover grupo. La lista de enlaces individuales funciona bien también. Doble enlace es mejor con SQL en mi opinión, sin embargo. La lista de enlaces individuales requiere que tenga toda la lista.

¿Qué hay de usar una implementación de lista vinculada? Al tener una columna, se mantendrá el valor (número de orden) del siguiente elemento. Creo que es de lejos el más fácil de usar al hacer la inserción de pedidos en el medio. No es necesario volver a numerar.

Lamentablemente, no hay una solución mágica para esto. No puede garantizar el orden de ninguna instrucción SELECT SIN una cláusula order by. Necesita agregar la columna y el progtwig a su alrededor.

No sé si recomendaría agregar espacios vacíos en la secuencia de pedidos, dependiendo del tamaño de sus listas y de los hits en el sitio, es posible que gane muy poco por el manejo excesivo de la lógica (aún necesitaría para atender a la ocasión donde se han agotado todas las lagunas). Echaré un vistazo de cerca para ver qué beneficios esto te daría en tu situación.

Lo siento, no puedo ofrecer nada mejor, espero que esto haya sido de ayuda.

No recomendaría el enfoque A, AA, B, BA, BB en absoluto. Hay un montón de procesamiento adicional involucrado para determinar la jerarquía y la inserción de entradas en el medio no es nada divertido.

Solo agregue un OrderField, entero. No use huecos, porque entonces tiene que trabajar con un ‘paso’ no estándar en su siguiente inserción del medio, o tendrá que volver a sincronizar su lista primero, luego agregar una nueva entrada.

Tener 0 … N es fácil de reordenar, y si puede usar métodos de Array o métodos de Lista fuera de SQL para reordenar la colección como un todo, luego actualice cada entrada, o puede averiguar dónde se está insertando, y +1 o -1 cada entrada después o antes de eso en consecuencia.

Una vez que tenga una pequeña biblioteca escrita, será pan comido.

Solo insertaría un campo de orden. Es la forma más simple. Si el cliente puede reordenar los campos o necesita insertarlos en el medio, simplemente reescriba los campos de pedidos para todos los artículos en ese lote.

Si en el futuro encuentra esta limitación debido al bajo rendimiento en las inserciones y actualizaciones, entonces es posible usar un campo varchar en lugar de un número entero. Esto permite un alto nivel de precisión cuando se inserta. por ejemplo, para insertar entre los elementos “A” y “B” puede insertar un artículo ordenado como “AA”. Sin embargo, esto es casi demasiado caro para un carrito de compras.

En un nivel de abstracción por encima del carrito Elementos digamos CartOrder (que tiene 1-n con CartItem) puede mantener un campo llamado itemOrder que podría ser solo una lista de identificadores separados por comas (PK) de registros cartItem relevantes. Será en la capa de aplicación lo que requiera para analizar eso y organizar sus modelos de elementos en consecuencia. La gran ventaja de este enfoque será en el caso de reorganizaciones de pedidos, puede que no haya cambios en los objetos individuales, pero dado que el orden se conserva como un campo de índice dentro de las filas de la tabla de elementos de orden, deberá emitir un comando de actualización para cada uno de los filas actualizando su campo de índice. Háganme saber sus críticas sobre este enfoque, tengo curiosidad por saber de qué manera podría fallar.

Lo resolví pragmáticamente así:

  1. El orden se define en la interfaz de usuario.

  2. El servidor recibe una solicitud POST que contiene los ID y la posición correspondiente de cada elemento en la lista.

  3. Comienzo una transacción y actualizo la posición para cada ID.

Hecho.

Entonces ordenar es caro, pero leer la lista ordenada es muy barato.

Yo recomendaría mantener huecos en el número de orden, así que en lugar de 1,2,3, etc., use 10,20,30 … Si necesita insertar solo un elemento más, puede ponerlo a 15, en lugar de reordenar todo en ese punto.

Bueno, yo diría que la respuesta corta es:

Cree una clave primaria de autoidentidad en la tabla de contenedores de inventario, luego inserte las filas en el orden correcto de arriba hacia abajo. Luego, al seleccionar de la tabla con el orden de la columna de autoidentidad de la clave principal, obtendrá la misma lista. Al hacer esto, debe eliminar todos los elementos y volver a insertarlos en caso de alteraciones en el contenido del carrito. (Pero esa es una forma bastante limpia de hacerlo). Si eso no es factible, vaya a la columna de pedidos como sugirieron otros.

Cuando uso Hibernate y necesito guardar el orden de @OneToMany , uso un Map y no una List .

 @OneToMany(fetch = FetchType.EAGER, mappedBy = "rule", cascade = CascadeType.ALL) @MapKey(name = "position") @OrderBy("position") private Map actions = LazyMap.decorate(new LinkedHashMap<>(), FactoryUtils.instantiateFactory(RuleAction.class, new Class[] { Rule.class }, new Object[] { this })); 

En este ejemplo de Java, la position es una propiedad Integer de RuleAction por lo que la orden se conserva de esa manera. Creo que en C # esto se vería bastante similar.