.NET 4.6(VB)游戏网站DataTable权限校验性能优化问询
优化.NET 4.6 VB DataTable权限校验的高效方案
你的问题很典型——当数据量从几百涨到上千级时,逐行遍历DataTable的操作很容易成为性能瓶颈。咱们先拆解下当前代码的核心问题:
- 每个GameID单独调用
CanViewOnGameList/CanEditGameContent等方法,大概率存在重复的数据库查询或缓存访问,1500次调用就是1500次IO开销 - 逐行调用
dr.Delete()和AcceptChanges(),DataTable的行删除是O(n)操作,频繁触发会导致大量内存移位和状态变更 - 每行单独更新字段后立即
AcceptChanges(),没必要的状态同步会增加额外开销
下面是几个针对性的优化方案,按实现难度和性能提升排序:
1. 批量获取权限集合(最优先优化)
把多次单GameID的权限查询,改成一次性获取当前用户所有有权限的GameID集合,从根源减少IO次数。
示例代码:
' 第一步:批量获取当前用户的所有权限GameID集合 Dim viewableGameIDs As New HashSet(Of Integer)(GetUserViewableGameIDs(currentUserID)) ' 合并CanEditGameContent和CanEditGameInfo的权限到同一个集合 Dim editableGameIDs As New HashSet(Of Integer)(GetUserEditableGameIDs(currentUserID)) Dim playableGameIDs As New HashSet(Of Integer)(GetUserPlayableGameIDs(currentUserID)) ' 第二步:复制原表并批量处理 Dim tmpGameList As DataTable = fullGameList.Copy ' 先筛选出不可见的游戏并批量删除 Dim nonViewableRows() As DataRow = tmpGameList.Select($"gameID NOT IN ({String.Join(",", viewableGameIDs)})") For Each dr As DataRow In nonViewableRows dr.Delete() Next ' 批量更新可编辑和可玩状态 For Each dr As DataRow In tmpGameList.Rows dr("isEditableGame") = If(editableGameIDs.Contains(CInt(dr("gameID"))), 1, 0) dr("isPlayableGame") = If(playableGameIDs.Contains(CInt(dr("gameID"))), 1, 0) Next ' 最后统一提交所有变更 tmpGameList.AcceptChanges() myGameList = tmpGameList
说明:GetUserViewableGameIDs等方法需要调整为批量查询,比如用SQL的WHERE userID = @ID直接返回所有符合条件的gameID列表,而不是单ID查询。
2. 用DataView筛选替代逐行删除
如果不需要保留原表结构的修改,用DataView的RowFilter可以直接过滤出可见游戏,避免删除行的开销:
' 先拼接可见GameID的字符串 Dim viewableIDsStr As String = String.Join(",", viewableGameIDs) Dim dv As New DataView(fullGameList) dv.RowFilter = $"gameID IN ({viewableIDsStr})" ' 把过滤后的DataView转成新的DataTable Dim tmpGameList As DataTable = dv.ToTable() ' 再批量更新权限状态 For Each dr As DataRow In tmpGameList.Rows dr("isEditableGame") = If(editableGameIDs.Contains(CInt(dr("gameID"))), 1, 0) dr("isPlayableGame") = If(playableGameIDs.Contains(CInt(dr("gameID"))), 1, 0) Next myGameList = tmpGameList
3. 改用强类型集合+LINQ(长期优化方向)
DataTable本质是弱类型的,遍历和修改的性能不如强类型对象集合。可以先把fullGameList转成List(Of GameModel),用LINQ操作后再转回DataTable:
示例:
' 定义强类型游戏模型 Public Class GameModel Public Property GameID As Integer Public Property IsEditableGame As Integer Public Property IsPlayableGame As Integer ' 其他游戏字段(如游戏名称、图标等)... End Class ' 把DataTable转换为强类型集合 Dim gameList As List(Of GameModel) = fullGameList.AsEnumerable().Select(Function(dr) New GameModel With { .GameID = CInt(dr("gameID")), ' 映射其他需要的字段 }).ToList() ' 用LINQ筛选可见游戏并更新权限状态 Dim filteredList = gameList.Where(Function(g) viewableGameIDs.Contains(g.GameID)).Select(Function(g) g.IsEditableGame = If(editableGameIDs.Contains(g.GameID), 1, 0) g.IsPlayableGame = If(playableGameIDs.Contains(g.GameID), 1, 0) Return g End Function).ToList() ' 转回DataTable(如果需要绑定UI) myGameList = filteredList.ToDataTable()
注:ToDataTable()可以自己实现一个扩展方法,.NET 4.6支持简单的反射转换逻辑,也可以借助成熟的第三方库完成。
4. 减少不必要的AcceptChanges调用
原代码中每行修改后都调用dr.AcceptChanges(),这完全没必要——只需要在所有行修改/删除完成后,统一调用tmpGameList.AcceptChanges()即可,能减少大量的状态同步开销。
内容的提问来源于stack exchange,提问作者SkyeBoniwell
相关产品推荐
相关产品推荐

