Je suis récemment passé à VS 2010 et je m'amuse avec LINQ to Dataset. J'ai un jeu de données fortement typé pour l'autorisation qui est dans HttpCache d'une WebApplication ASP.NET.
Je voulais donc savoir quel est le moyen le plus rapide de vérifier si un utilisateur est autorisé à faire quelque chose. Ici est mon modèle de données et quelques autres informations si quelqu'un est intéressé.
J'ai vérifié de 3 façons :
- direct base de données
- Requête LINQ avec Où conditions comme "Join" - Syntaxe
- Requête LINQ avec Rejoignez - Syntaxe
Voici les résultats avec 1000 appels sur chaque fonction :
1. itération :
- 4,2841519 sec.
- 115,7796925 sec.
- 2,024749 sec.
2. itération :
- 3,1954857 sec.
- 84,97047 sec.
- 1,5783397 sec.
3. itération :
- 2,7922143 sec.
- 97,8713267 sec.
- 1,8432163 sec.
Moyenne :
- Base de données : 3,4239506333 sec.
- Où : 99,5404964 sec.
- Joindre : 1,815435 sec.
Pourquoi la version Join est-elle tellement plus rapide que la syntaxe where qui la rend inutile bien qu'en tant que novice de LINQ, elle semble être la plus lisible. Ou ai-je manqué quelque chose dans mes requêtes ?
Voici les requêtes LINQ, je saute la base de données :
Où :
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
Rejoignez-nous :
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
Merci d'avance.
Editar Après quelques améliorations sur les deux requêtes pour obtenir des valeurs de performance plus significatives, l'avantage du JOIN est encore beaucoup plus grand qu'avant :
Rejoignez :
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
Où :
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
Résultat pour 1000 appels (sur un ordinateur plus rapide)
- Rejoindre | 2. où
1. itération :
- 0,0713669 sec.
- 12,7395299 sec.
2. itération :
- 0,0492458 sec.
- 12,3885925 sec.
3. itération :
- 0,0501982 sec.
- 13,3474216 sec.
Moyenne :
- Joindre : 0,0569367 sec.
- Où : 12,8251813 sec.
La jointure est 225 fois plus rapide
Conclusion : éviter WHERE pour spécifier les relations et utiliser JOIN chaque fois que possible (définitivement dans LINQ à DataSet y Linq-To-Objects
en général).