【问题标题】:Best Practice to renumber items in a list? SQL or C#/VB.NET重新编号列表中的项目的最佳实践? SQL 或 C#/VB.NET
【发布时间】:2009-07-02 04:02:54
【问题描述】:

我有一个包含 SortOrder 整数列的数据库表。在用于添加和编辑表格项目的 UI 中,我有一个整数下拉列表,让用户选择他们希望该项目出现在排序顺序中的哪个位置。我的问题是,比如说列表 {1,2,3,4,5,"last"},如果用户选择一个数字,我希望它是 items SortOrder 属性,然后是具有“SortOrder”的项目当前将增加一个(+ = 1)以及具有较高“SortOrder”的项目,同时不影响具有较低“SortOrder”的项目。 我目前有一个使用 VB.NET 和 Linq 的公共模块“实用程序”

Private _db 作为新的 MyDataContext

Public Sub UpdateProductSortOrder(ByVal idx As Integer)

    Dim products = (From p As Product In _db.Products _
        Where p.SortOrder >= idx _
        Select p).ToList()

    For Each p As Product In products
        p.SortOrder += 1
    Next

    _db.SubmitChanges()

End Sub

当我这样做时添加项目似乎工作正常

Protected Overrides Sub AddItem()

    Dim sortOrder As Integer = Int32.Parse(Server.HtmlEncode(ddlNewSortOrder.SelectedValue))

    If (sortOrder >= 1) Then
        Utilities.UpdateProductSortOrder(sortOrder)
    Else
        sortOrder = Utilities.GetNextProductSortOrder()
    End If

    Dim dic As New System.Collections.Specialized.ListDictionary()
    dic.Add("PROD_Description", Server.HtmlEncode(txtNewDescription.Text))
    dic.Add("Abbrev", Server.HtmlEncode(txtNewAbbreviation.Text.ToUpper()))
    dic.Add("SortOrder", sortOrder)

    ProductsGridSource.Insert(dic)

End Sub

但是在编辑这样的现有项目时,我偶尔会遇到一些错误

受保护的子 ProductsGridSource_Updating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.LinqDataSourceUpdateEventArgs) Dim sortOrder As Integer = DirectCast(e.NewObject, Product).SortOrder 实用程序.UpdateProductSortOrder(sortOrder) 结束子

是否有更有效的最佳实践方式,我应该这样做? 任何建议表示赞赏。

提前致谢, ~ck 在圣地亚哥

【问题讨论】:

    标签: linq sequence linqdatasource


    【解决方案1】:

    编辑的技巧是您不想更新每个数字,只更新受更改影响的数字。对于一个项目,这很容易,但如果您一次编辑多个项目,我会将这些项目存储在按 SortOrder 排序的列表中:

    Dim products = (From p As Product In _db.Products _
            Order By p.SortOrder _
            Select p).ToList()
    

    然后我会根据新值重新排列列表:

    // do a RemoveAt first if you need to move an item
    products.InsertAt(sortOrder, dic); 
    

    然后重新编号所有内容(如果您想优化,则重新编号以 SortOrder 开头的所有内容):

    Dim index As Integer = 0
    For Each p As Product In products
        p.SortOrder = index
        index += 1
    Next
    

    如果您在一个块中完成所有重新排列然后在一个块中进行更新,您将节省一些多余的工作。

    如果您有一个大的记录集,这种方法就不能很好地工作。在这种情况下,您需要制定更有效的方法,例如使用数据库为您完成工作。

    DECLARE @sortOrder INT
    DECLARE @maxSortOrder INT
    SET @sortOrder = 5
    SET @maxSortOrder = 10
    UPDATE Products SET SortOrder = SortOrder + 1 
    WHERE SortOrder >= @sortOrder AND SortOrder < @maxSortOrder
    

    【讨论】:

      【解决方案2】:

      在编辑项目的 SortOrder 时,您需要原始值和新值。

      如果您的列表中有 5 个项目:

      1. 项目 A
      2. B 项
      3. C 项
      4. 项目 D
      5. 项目 E

      如果您想将项目 D 移动到位置 2,那么您只需要增加项目 B 和 C 的 SortOrder 值。

      或者,如果您将项目 B 向下移动到位置 4,那么您需要减少项目 C 和 D 的 SortOrder 值。

      我会将您的 UpdateProductSortOrder 方法重命名为 InsertProductSortOrder,然后编写一个新方法 UpdateProductSortOrder,它需要 2 个参数。

      Public Sub UpdateProductSortOrder(ByVal originalIdx As Integer, ByVal newIdx As Integer)
      

      当我处理此类问题时,它可以帮助我在纸上写下所有场景并绘制箭头以查看列表中需要进行哪些更改。

      【讨论】:

      • 我喜欢这种方法。是的,我可以看到我的问题。我正在更改不需要更改的值,只需将 1 添加到所有内容。如何使用 Linq 有效地实现这一点?
      【解决方案3】:

      这是一个多用户系统吗?如果是这样,您需要考虑到这一点。一种方法是在增加值时锁定数据库。否则,如果两个用户同时运行代码,您可能会收到损坏的数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-24
        • 2010-10-19
        • 1970-01-01
        • 1970-01-01
        • 2019-07-10
        • 2011-10-27
        • 1970-01-01
        相关资源
        最近更新 更多