更新语句以保持对数据库中SortOrder的跟踪
本文关键字:SortOrder 跟踪 数据库 语句 更新 | 更新日期: 2023-09-27 18:03:23
我在屏幕上有一个产品图像列表。当用户拖放图像时,我可以访问oldIndex和newIndex。
假设我有以下内容:
Product1[指数:0]
Product2[指数:1]
Product3[指数:2]
Product4[指数:3]
Product5[指数:4]
Product6[index: 5]
用户决定将Product2放在Product4之前
我想弄清楚我的db更新语句是什么。我正在阅读另一篇文章,看到有人说你应该更新>= newIndex的所有产品的SortOrder字段,然后更新新产品以在newIndex中。
这对我来说似乎有些不对劲,这会给我留下以下内容:
Product1[指数:0]
Product2[指数:2]
Product3[指数:3]
Product4[指数:4]
Product5[指数:5]
Product6(指数:6)
我真的在努力实现这一点,我的索引保持在完美的顺序,没有间隙。有什么建议吗?
所以我写了一个void来处理这些繁琐的工作。因为我需要处理多种类型的实体,它们都有一个SortOrder
列,所以我创建了一个名为ISortable
的接口,它包含一个SortOrder
列。如果您只对一个db表执行此操作,则可以用您的实体命名的任何名称替换ISortable
的任何实例。
在这个void之外需要发生的是:
从db中获取项目并将其旧排序顺序存储在变量(oldSortOrder
)中,然后设置项目的新排序顺序(newSortOrder
),然后设置变量为所有其他项目,而不是您刚刚更新的项目(list
)。这也说明了从数据库中删除的项目,只需在ajax调用中将newSortOrder
设置为0
。
WebApi方法:
// Code is activated when accessed via http PUT
public void PutItem(int itemId, int newSortOrder)
{
// using makes sure Context is disposed of properly
using (var Context = new MyDbContext())
{
var oldSortOrder = 0;
IEnumerable<ISortable> itemsToReorder = null;
// Get moved item from database
var item = Context.Items.FirstOrDefault(x => x.ItemId == itemId);
// Before we set the new sort order, set a variable to the
// old one. This will be used to reorder the other items.
oldSortOrder = item.SortOrder;
// Get all items except the one we grabbed above.
itemsToReorder = Context.Items.Where(x => x.ItemId != itemId);
// Delete if the item is set for deletion (newSortOrder = 0)
if (newSortOrder == 0)
{
Context.Items.Remove(item);
}
// Otherwise, set the new sort order.
else
{
item.SortOrder = newSortOrder;
}
// Pass other items into reordering logic.
ReOrder(itemsToReorder, oldSortOrder, newSortOrder);
// Save all those changes back to the database
Context.SaveChanges();
}
}
重新排序无效:
public static void ReOrder(IEnumerable<ISortable> list,
int oldSortOrder,
int newSortOrder)
{
IEnumerable<ISortable> itemsToReorder;
// Pare down the items to just those that will be effected by the move.
// New sort order of 0 means the item has been deleted.
if (newSortOrder == 0)
{
itemsToReorder = list.Where(x => x.SortOrder > oldSortOrder);
}
else
{
// This is just a long inline if statement. Applies Where()
// conditions depending on the old and new sort variables.
itemsToReorder = list.Where(x => (oldSortOrder < newSortOrder
? x.SortOrder <= newSortOrder &&
x.SortOrder > oldSortOrder
: x.SortOrder >= newSortOrder &&
x.SortOrder < oldSortOrder));
}
foreach (var i in itemsToReorder)
{
// Original item was moved down
if (newSortOrder != 0 && oldSortOrder < newSortOrder)
{
i.SortOrder -= 1;
}
// Original item was moved up
else if (newSortOrder != 0 && oldSortOrder > newSortOrder)
{
i.SortOrder += 1;
} // Original item was removed.
else
{
i.SortOrder -= 1;
}
}
}
如果你需要澄清,请告诉我。我几乎可以肯定,我没有把每件事都解释清楚。
IF OBJECT_ID('tempdb..#Product') IS NOT NULL
DROP TABLE #Product
CREATE TABLE #Product(
Name VARCHAR(100) NOT NULL
,SortOrder INT NOT NULL
)
INSERT INTO #Product (Name, SortOrder)
VALUES
('Product1', 0)
,('Product2', 1)
,('Product3', 2)
,('Product4', 3)
,('Product5', 4)
,('Product6', 5)
DECLARE
@NewIndex INT
,@OldIndex INT
SET @OldIndex = 4 --'Product5'
SET @NewIndex = 2 -- After 'Product2'
IF @NewIndex < @OldIndex -- Move UP
UPDATE #Product
SET SortOrder = CASE
WHEN SortOrder = @OldIndex THEN @NewIndex
ELSE SortOrder + 1
END
WHERE SortOrder BETWEEN @NewIndex AND @OldIndex;
ELSE -- Move DOwn
UPDATE #Product
SET SortOrder = CASE
WHEN SortOrder = @OldIndex THEN @NewIndex
ELSE SortOrder - 1
END
WHERE SortOrder BETWEEN @OldIndex AND @NewIndex;
SELECT * FROM #Product ORDER BY SortOrder