Il modo migliore per salvare un elenco ordinato nel database mantenendo l’ordine

Mi stavo chiedendo se qualcuno ha una buona soluzione per un problema che ho riscontrato numerose volte negli ultimi anni.

Ho un carrello della spesa e il mio cliente richiede esplicitamente che l’ordine è significativo. Quindi ho bisogno di mantenere l’ordine nel DB.

Il modo ovvio sarebbe semplicemente inserire alcuni OrderField dove assegnerei il numero da 0 a N e lo selezionerei in quel modo.

Ma fare ciò renderebbe il riordino più difficile e in qualche modo ritengo che questa soluzione sia piuttosto fragile e tornerà un giorno a me.

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

Grazie

FWIW, penso che il tuo modo di suggerire (cioè di commettere l’ordine nel database) non sia una ctriggers soluzione al tuo problema. Penso anche che sia probabilmente il modo più sicuro / più affidabile.

Ok ecco la mia soluzione per rendere la programmazione più semplice per chiunque si trovi in ​​questa discussione. il trucco è essere in grado di aggiornare tutti gli indici degli ordini sopra o sotto un inserimento / cancellazione in un aggiornamento.

Utilizzando una colonna numerica (numero intero) nella tabella, supportata dalle query SQL

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

Per eliminare l’articolo al numero 6:

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

Per scambiare due elementi (4 e 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; 

cioè 0 non è usato, quindi usalo come manichino per evitare di avere un object ambiguo.

Per inserire a 3:

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

La soluzione migliore è una lista Doubly Linked . O (1) per tutte le operazioni tranne l’indicizzazione. Nulla può indicizzare SQL velocemente, tranne che con una clausola where sull’elemento desiderato.

0,10,20 tipi falliscono. Le colonne di sequenza falliscono. La colonna della sequenza fluttuante fallisce nei movimenti di gruppo.

La lista Doubly Linked è uguale per le operazioni di aggiunta, rimozione, cancellazione di gruppo, aggiunta di gruppo, spostamento di gruppo. Anche la singola lista collegata funziona bene. Double link è meglio con SQL, a mio avviso però. Un singolo elenco collegato richiede di avere l’intero elenco.

Che ne dici di utilizzare un’implementazione di elenchi collegati? Avendo una colonna, si terrà il valore (numero ordine) dell’articolo successivo. Penso che sia di gran lunga il più facile da usare quando si fa l’inserimento di ordini nel mezzo. Non c’è bisogno di rinumerare.

Sfortunatamente non esiste una pallottola magica per questo. Non è ansible garantire l’ordine di qualsiasi istruzione SELECT SENZA un ordine per clausola. È necessario aggiungere la colonna e programmare attorno ad essa.

Non so che raccomanderei di aggiungere lacune nella sequenza degli ordini, a seconda della dimensione delle tue liste e dei colpi sul sito, potresti guadagnare molto poco per gestire la logica (dovresti comunque aver bisogno per soddisfare l’occasione in cui tutte le lacune sono state esaurite). Darei un’occhiata da vicino per vedere quali benefici questo ti avrebbe dato nella tua situazione.

Scusa, non posso offrire niente di meglio, spero che questo sia stato di aiuto.

Non raccomanderei assolutamente l’approccio A, AA, B, BA, BB. C’è un sacco di ulteriore elaborazione coinvolta per determinare la gerarchia e l’inserimento di voci intermedie non è affatto divertente.

Basta aggiungere un OrderField, intero. Non utilizzare spazi vuoti, perché in questo caso devi lavorare con un “passaggio” non standard sul tuo prossimo inserto centrale, oppure dovrai risincronizzare prima l’elenco, quindi aggiungere una nuova voce.

Avere 0 … N è facile da riordinare, e se è ansible utilizzare i metodi Array o List al di fuori di SQL per riordinare la raccolta nel suo complesso, quindi aggiornare ogni voce, oppure è ansible capire dove si sta inserendo, e +1 o -1 ogni voce dopo o prima di conseguenza.

Una volta scritta una piccola libreria, sarà un gioco da ragazzi.

Vorrei solo inserire un campo dell’ordine. È il modo più semplice. Se il cliente può riordinare i campi o è necessario inserirlo nel mezzo, è sufficiente riscrivere i campi dell’ordine per tutti gli articoli di quel lotto.

Se lungo la linea si trova questa limitazione a causa delle scarse prestazioni su inserti e aggiornamenti, è ansible utilizzare un campo varchar anziché un intero. Ciò consente un livello abbastanza elevato di precisione durante l’inserimento. ad esempio per inserire tra gli elementi ‘A’ e ‘B’ è ansible inserire un articolo ordinato come ‘AA’. Questo è quasi certamente eccessivo per un carrello della spesa però.

A un livello di astrazione sopra il carrello Articoli diciamo CartOrder (che ha 1-n con CartItem) è ansible mantenere un campo chiamato itemOrder che potrebbe essere solo un elenco separato da virgola (PK) di record cartItem rilevanti. Sarà a livello di applicazione che è necessario analizzare e organizzare i modelli degli articoli di conseguenza. Il grande vantaggio di questo approccio sarà nel caso di rimescolamenti degli ordini, potrebbero non esserci modifiche sui singoli oggetti ma poiché l’ordine è persistente come un campo indice all’interno delle righe della tabella degli articoli dell’ordine sarà necessario emettere un comando di aggiornamento per ognuno dei righe che aggiornano il loro campo indice. Per favore fatemi sapere le vostre critiche su questo approccio, sono curioso di sapere in che modo questo potrebbe fallire.

L’ho risolto pragmaticamente in questo modo:

  1. L’ordine è definito nell’interfaccia utente.

  2. Il backend riceve una richiesta POST che contiene gli ID e la posizione corrispondente di ogni elemento nell’elenco.

  3. Inizio una transazione e aggiorno la posizione per ogni ID.

Fatto.

Quindi ordinare è costoso ma leggere l’elenco ordinato è super economico.

Ti suggerisco di mantenere le lacune nel numero dell’ordine, quindi invece di 1,2,3, ecc., Usa 10,20,30 … Se devi inserire solo un altro elemento, potresti metterlo a 15, invece di riordinare tutto a quel punto.

Bene, direi che la risposta breve è:

Creare una chiave primaria di autoidentity nella tabella cartcontents, quindi inserire le righe nell’ordine top-down corretto. Quindi, selezionando dalla tabella con l’ordine dalla colonna di autoid quadro della chiave primaria si otterrebbe la stessa lista. In questo modo è necessario eliminare tutti gli elementi e reinserire quindi in caso di modifiche al contenuto del carrello. (Ma questo è ancora un modo abbastanza pulito di farlo) Se ciò non è fattibile, allora vai con la colonna degli ordini come suggerito da altri.

Quando utilizzo Hibernate e devo salvare l’ordine di un @OneToMany , utilizzo una Map e non 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 })); 

In questo esempio Java, position è una proprietà Integer di RuleAction modo che l’ordine sia mantenuto in quel modo. Immagino che in C # sembrerebbe piuttosto simile.