Лучший способ сохранить упорядоченный список в базе данных при сохранении заказа



Мне было интересно, есть ли у кого-нибудь хорошее решение проблемы, с которой я сталкивался много раз за последние годы.



У меня есть корзина и мой клиент явно указал, что порядок имеет значение. Поэтому мне нужно сохранить порядок в БД.



очевидным способом было бы просто вставить некоторое поле OrderField, где я бы присвоил число 0 N и отсортировал его таким образом.



но это сделало бы переупорядочивание сложнее, и я как-то чувствую, что это решение довольно хрупкое и когда-нибудь вернется ко мне.



(Я использую C# 3,5 с NHibernate и SQL Server 2005)



спасибо

638   12  

12 ответов:

FWIW, я думаю, что способ, который вы предлагаете (т. е. фиксация заказа в базе данных), не является плохим решением вашей проблемы. Я также думаю, что это, вероятно, самый безопасный/самый надежный способ.

ОК, Вот мое решение, чтобы сделать программирование легче для тех, кто бывает на этой ветке. трюк заключается в том, чтобы обновить все индексы ордеров выше или ниже вставки / удаления в одном обновлении.

использование числового (целочисленного) столбца в таблице, поддерживаемого SQL-запросами

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

, чтобы удалить элемент в orderindex 6:

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

для замены двух элементов (4 и 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;

т. е. 0 не используется, поэтому используйте его как a манекен, чтобы избежать неоднозначного элемента.

вставить в 3:

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

лучшее решение-это двусвязный список. O (1) для всех операций, кроме индексации. Ничто не может быстро индексировать SQL, за исключением предложения where для элемента, который вы хотите.

0,10,20 типы терпят неудачу. Последовательность столбцов не удается. Столбец последовательности поплавок не перемещается.

дважды связанный список-это те же операции для добавления, удаления, удаления группы, добавления группы, перемещения группы. Один связанный список тоже работает нормально. Double linked лучше с SQL на мой взгляд хотя. Один связанный список требует, чтобы у вас был весь список.

Как насчет использования реализации связанного списка? Имея один столбец будет содержать значение (номер заказа) следующего элемента. Я думаю, что это, безусловно, самый простой в использовании при выполнении вставки заказов между ними. Нет необходимости перенумеровывать.

к сожалению, для этого нет волшебной пули. Вы не можете гарантировать порядок любого SELECT оператор без предложения order by. Вам нужно добавить столбец и программу вокруг него.

Я не знаю, что я бы рекомендовал добавлять пробелы в последовательности заказов, в зависимости от размера ваших списков и хитов на сайте, вы можете получить очень мало для обработки логики (вам все равно нужно будет обслуживать случай, когда все пробелы были использованы). Я бы взял внимательно посмотрите, какие преимущества это даст вам в вашей ситуации.

к сожалению я не могу предложить ничего лучше, надеюсь, что это помогло.

Я бы не рекомендовал подход A, AA, B, BA, BB вообще. Существует много дополнительной обработки, связанной с определением иерархии и вставкой записей между ними, это совсем не весело.

просто добавьте OrderField, целое число. Не используйте пробелы, потому что тогда вам придется либо работать с нестандартным "шагом" на следующей средней вставке, либо вам придется сначала синхронизировать свой список, а затем добавить новую запись.

с 0...N легко переупорядочить, и если вы можете использовать массив методы или методы списка за пределами SQL, чтобы изменить порядок коллекции в целом, а затем обновить каждую запись, или вы можете выяснить, где вы вставляете, и +1 или -1 каждая запись после или перед ней соответственно.

Если у вас есть маленькая библиотека, написанная для него, это будет кусок пирога.

Я бы просто вставил поле заказа. Это самый простой способ. Если клиент может изменить порядок полей или вам нужно вставить в середину, то просто перепишите поля заказа для всех позиций в этой партии.

Если в нижней строке вы найдете это ограничение из-за низкой производительности при вставках и обновлениях, то можно использовать поле varchar, а не целое число. Это позволяет обеспечить довольно высокий уровень точности при вставке. например, чтобы вставить между элементами " A " и "B", вы можете вставить товар заказывается как 'AA'. Это почти наверняка перебор для корзины покупок, хотя.

на уровне абстракции над элементами корзины скажем CartOrder(который имеет 1-n с CartItem) вы можете поддерживать поле под названием itemOrder, которое может быть просто разделенным запятыми списком id (PK) соответствующих записей cartItem . Это будет на уровне приложения, что вам нужно проанализировать, что и организовать ваши модели элементов соответственно . Большой плюс для этого подхода будет в случае перестановок порядка , не может быть изменений на отдельных объектах, но поскольку порядок сохраняется как поле индекса внутри строк таблицы элементов заказа для каждой строки, обновляющей поле индекса, необходимо ввести команду обновления. Пожалуйста, дайте мне знать ваши критические замечания по этому подходу, мне любопытно знать, каким образом это может потерпеть неудачу.

Я решил прагматически такой:

  1. порядок определяется в пользовательском интерфейсе.

  2. серверная часть получает запрос POST, который содержит идентификаторы и соответствующую позицию каждого элемента в списке.

  3. Я запускаю транзакцию и обновляю позицию для каждого идентификатора.

сделано.

поэтому заказ стоит дорого, но чтение упорядоченного списка очень дешево.

Я бы рекомендовал держать пробелы в номере заказа, поэтому вместо 1,2,3 и т. д. Используйте 10,20,30... Если вам нужно просто вставить еще один элемент, вы можете поместить его в 15, а не переупорядочивать все в этой точке.

Ну, я бы сказал, что короткий ответ:

создайте первичный ключ autoidentity в таблице cartcontents, затем вставьте строки в правильном порядке сверху вниз. Затем, выбрав из таблицы с порядком по столбцу первичного ключа autoidentity, вы получите тот же список. Таким образом, вы должны удалить все элементы и снова вставить их в случае изменения содержимого корзины. (Но это все еще довольно чистый способ сделать это), если это невозможно, то обращаться с заказом колонка, как предлагают другие.

когда я использую Hibernate, и нужно сохранить порядок a @OneToMany, Я использую Map, а не List.

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

в этом примере Java position является целочисленным свойством RuleAction таким образом, порядок сохраняется таким образом. Я думаю в C# это будет выглядеть довольно похожие.

Comments

    Ничего не найдено.