我最近升级到了VS 2010,并且正在使用LINQ到Dataset。我在ASP.NET WebApplication的HttpCache中有一个用于授权的强类型数据集。
所以我想知道检查用户是否有权做某事的最快方法是什么。如果有人感兴趣,这是我的数据模型和其他一些信息。
我检查了3种方法:
- 直接数据库
- 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版本比where语法快得多,这使得它变得毫无用处,尽管作为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倍
结论:避免在哪里指定关系,并尽可能使用JOIN(在LINQ to DataSet中和Linq-To-Objects
一般情况下肯定是这样)。
Join
,如果可以从头开始编写优化的代码,为什么要依赖优化器呢?这也使您的意图更加清晰。因此,出于同样的原因,您应该在sql中选择JOIN。