在保持sorting的同时将有序列表保存到数据库的最佳方法
我想知道如果有人能够很好地解决我在过去几年中遇到过的很多问题。
我有一个购物车,我的客户明确要求它的顺序是重要的。 所以我需要坚持到DB的订单。
显而易见的方法是简单地插入一些OrderField,我将数字0赋值给N,然后按这种方式sorting。
但是这样做会使重新sorting变得困难,我觉得这个解决scheme有点脆弱,有一天会回来。
(我用NHibernate和SQL Server 2005使用C#3,5)
谢谢
FWIW,我想你的build议(即提交到数据库的顺序)不是一个不好的解决scheme,你的问题。 我也认为这可能是最安全/最可靠的方法。
好的,这里是我的解决scheme,使这个线程发生的任何人更容易编程。 诀窍是能够在一次更新中更新插入/删除之上或之下的所有订单索引。
在表中使用数字(整数)列,由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不使用,所以使用它作为一个虚拟,以避免有一个模棱两可的项目。
以3:
UPDATE myitems SET orderindex = (orderindex + 1) WHERE orderindex > 2; INSERT INTO myitems (Myitem,orderindex) values ("MytxtitemHere",3)
最好的解决scheme是双链表 。 O(1)除索引外的所有操作。 没有什么可以快速索引SQL,除了你想要的项目的where子句。
0,10,20types失败。 序列列的失败。 浮动顺序列在组移动时失败。
双向链接列表是添加,删除,组删除,组添加,组移动相同的操作。 单链表也可以。 在我看来,双链接与SQL更好。 单链表要求你有整个列表。
如何使用链表实现? 有一列将保存下一个项目的值(订单号)。 我认为这是在插入订单时最简单的方法。 无需重新编号。
不幸的是,这没有什么灵丹妙药。 您无法保证任何SELECT
语句的顺序,而无需order by子句。 你需要围绕它添加列和程序。
我不知道我会build议在顺序序列中添加空白,这取决于列表的大小和网站上的点击量,对于处理逻辑的头部,你可能会获得很less(你仍然需要以迎合所有差距已经用完的场合)。 我会仔细看看这会给你带来什么样的好处。
对不起,我不能提供更好的,希望这有助于。
我不会推荐A,AA,B,BA,BB的方法。 有很多额外的处理涉及到确定层次结构和插入条目之间是没有乐趣的。
只需添加一个OrderField,整数。 不要使用空白,因为那么你必须在下一个中间插入时使用非标准的“步骤”,否则你必须先重新同步你的列表,然后添加一个新的条目。
拥有0 … N很容易重新sorting,如果您可以使用SQL以外的Array方法或List方法重新整理集合,然后更新每个条目,或者可以确定要插入的位置,并在相应的之前或之后input+1或-1。
一旦你有一个为它写的小库,它将是一块蛋糕。
我只是插入一个订单字段。 它是最简单的方法。 如果客户可以重新排列字段,或者需要在中间插入,那么只需重写该批次中所有项目的订单字段即可。
如果下线,你会发现这个限制,因为插入和更新性能差,那么可以使用varchar字段而不是整数。 插入时允许相当高的精确度。 例如在项目“A”和“B”之间插入,你可以插入一个项目为“AA”。 这几乎肯定是一个购物车矫枉过正。
在购物车上面的抽象级别上,比如说CartOrder(与CartItem有1-n),你可以维护一个名为itemOrder的字段,它可以是一个逗号分隔的cartItemlogging相关的id(PK)列表。 它将在应用程序层,您需要parsing并相应地安排您的项目模型。 这种方法的最大好处是在订单重组的情况下,单个对象可能不会发生变化,但是由于订单在订单项表格行中作为索引字段持续存在,所以您必须为每个订单项发出更新命令行更新其索引字段。 请让我知道你对这种方法的批评,我很想知道在哪些方面可能会失败。
我这样务实地解决了这个问题:
-
订单在用户界面中定义。
-
后端获取一个POST请求,其中包含列表中每个项目的ID和相应的位置。
-
我开始交易并更新每个ID的位置。
完成。
所以订购是昂贵的,但阅读有序列表是超级便宜的。
我会build议在订单号码中保留空白,所以不要使用1,2,3等,使用10,20,30 …如果您需要插入一个更多的项目,可以将它放在15,而不是重新sorting在那时候。
那么,我想说的简短答案是:
在cartcontents表中创build一个autoidentity主键,然后按照正确的从上到下的顺序插入行。 然后通过从主表中select主键自动识别列将给你相同的列表。 通过这样做,您必须删除所有项目,然后重新插入,以便更改购物车内容。 (但是,这样做还是相当干净的)如果这样做不可行,那么就像其他人所build议的一样,去订单栏。
当我使用Hibernate
,并且需要保存@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
的Integer属性,所以顺序是以这种方式保持的。 我想在C#中,这看起来很相似。