我最近升级到 VS 2010 并且正在使用 LINQ to Dataset。我有一个强类型的授权数据集,位于 ASP.NET WebApplication 的 HttpCache 中。
所以我想知道检查用户是否被授权做某事的最快方法实际上是什么。如果有人感兴趣,这是我的数据模型和其他一些信息。
我检查了3种方法:
- 直接数据库
- 使用Where条件作为“加入”的LINQ 查询- 语法
- 使用Join的 LINQ 查询- 语法
这些是每个函数调用 1000 次的结果:
1.迭代:
- 4,2841519 秒。
- 115,7796925 秒。
- 2,024749 秒。
2.迭代:
- 3,1954857 秒。
- 84,97047 秒。
- 1,5783397 秒。
3.迭代:
- 2,7922143 秒。
- 97,8713267 秒。
- 1,8432163 秒。
平均的:
- 数据库:3,4239506333 秒。
- 其中:99,5404964 秒。
- 加入:1,815435 秒。
为什么 Join-version 比 where-syntax 快得多,这使得它毫无用处,尽管作为 LINQ 新手,它似乎是最易读的。还是我在查询中遗漏了什么?
这是 LINQ 查询,我跳过了数据库:
哪里:
Public Function hasAccessDS_Where(ByVal accessRule As String) As Boolean
Dim userID As Guid = DirectCast(Membership.GetUser.ProviderUserKey, Guid)
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule, _
roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule, _
role In Authorization.dsAuth.aspnet_Roles, _
userRole In Authorization.dsAuth.aspnet_UsersInRoles _
Where accRule.idAccessRule = roleAccRule.fiAccessRule _
And roleAccRule.fiRole = role.RoleId _
And userRole.RoleId = role.RoleId _
And userRole.UserId = userID And accRule.RuleName.Contains(accessRule)
Select accRule.idAccessRule
Return query.Any
End Function
加入:
Public Function hasAccessDS_Join(ByVal accessRule As String) As Boolean
Dim userID As Guid = DirectCast(Membership.GetUser.ProviderUserKey, Guid)
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule _
Join roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule _
On accRule.idAccessRule Equals roleAccRule.fiAccessRule _
Join role In Authorization.dsAuth.aspnet_Roles _
On role.RoleId Equals roleAccRule.fiRole _
Join userRole In Authorization.dsAuth.aspnet_UsersInRoles _
On userRole.RoleId Equals role.RoleId _
Where userRole.UserId = userID And accRule.RuleName.Contains(accessRule)
Select accRule.idAccessRule
Return query.Any
End Function
先感谢您。
编辑:在对两个查询进行一些改进以获得更有意义的性能值之后,JOIN 的优势甚至比以前大很多倍:
加入:
Public Overloads Shared Function hasAccessDS_Join(ByVal userID As Guid, ByVal idAccessRule As Int32) As Boolean
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule _
Join roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule _
On accRule.idAccessRule Equals roleAccRule.fiAccessRule _
Join role In Authorization.dsAuth.aspnet_Roles _
On role.RoleId Equals roleAccRule.fiRole _
Join userRole In Authorization.dsAuth.aspnet_UsersInRoles _
On userRole.RoleId Equals role.RoleId _
Where accRule.idAccessRule = idAccessRule And userRole.UserId = userID
Select role.RoleId
Return query.Any
End Function
哪里:
Public Overloads Shared Function hasAccessDS_Where(ByVal userID As Guid, ByVal idAccessRule As Int32) As Boolean
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule, _
roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule, _
role In Authorization.dsAuth.aspnet_Roles, _
userRole In Authorization.dsAuth.aspnet_UsersInRoles _
Where accRule.idAccessRule = roleAccRule.fiAccessRule _
And roleAccRule.fiRole = role.RoleId _
And userRole.RoleId = role.RoleId _
And accRule.idAccessRule = idAccessRule And userRole.UserId = userID
Select role.RoleId
Return query.Any
End Function
1000 次呼叫的结果(在更快的计算机上)
- 加入 | 2. 在哪里
1.迭代:
- 0,0713669 秒。
- 12,7395299 秒。
2.迭代:
- 0,0492458 秒。
- 12,3885925 秒。
3.迭代:
- 0,0501982 秒。
- 13,3474216 秒。
平均的:
- 加入:0,0569367 秒。
- 其中:12,8251813 秒。
加入速度快 225 倍
结论:尽可能避免 WHERE 指定关系并使用 JOIN(绝对是在LINQ to DataSet和Linq-To-Objects
一般情况下)。