Ich habe kürzlich ein Upgrade auf VS 2010 durchgeführt und spiele mit LINQ to Dataset herum. Ich habe ein stark typisiertes Dataset für die Autorisierung, das sich in HttpCache einer ASP.NET-Webanwendung befindet.
Also wollte ich wissen, was eigentlich der schnellste Weg ist, um zu überprüfen, ob ein Benutzer berechtigt ist, etwas zu tun. Hier ist mein Datenmodell und einige andere Informationen, wenn jemand interessiert ist.
Ich habe 3 Möglichkeiten überprüft:
- Direkte Datenbank
- LINQ-Abfrage mit Where Bedingungen als "Join" - Syntax
- LINQ-Abfrage mit Join - Syntax
Dies sind die Ergebnisse mit 1000 Aufrufen für jede Funktion:
1.Iteration:
- 4,2841519 Sek.
- 115.7796925 Sek.
- 2,024749 Sek.
2.Iteration:
- 3,1954857 Sek.
- 84.97047 Sek.
- 1,5783397 Sek.
3.Iteration:
- 2,7922143 Sek.
- 97,8713267 sek.
- 1,8432163 Sek.
Durchschnittlich:
- Datenbank: 3,4239506333 Sek.
- Wo: 99.5404964 Sek.
- Beitritt: 1.815435 Sek.
Warum ist die Join-Version so viel schneller als die Where-Syntax, was sie unbrauchbar macht, obwohl sie als LINQ-Neuling am besten lesbar zu sein scheint. Oder habe ich etwas in meinen Fragen verpasst?
Hier sind die LINQ-Abfragen, ich überspringe die Datenbank:
Wo :
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
Beitreten:
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
Vielen Dank im Voraus.
Bearbeiten : Nach einigen Verbesserungen an beiden Abfragen, um aussagekräftigere Leistungswerte zu erhalten, ist der Vorteil von JOIN sogar um ein Vielfaches größer als zuvor:
Mitmachen :
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
Wo :
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
Ergebnis für 1000 Anrufe (auf einem schnelleren Computer)
- Beitreten | 2. Wo
1.Iteration:
- 0,0713669 Sek.
- 12.79595299 Sek.
2.Iteration:
- 0,0492458 Sek.
- 12.3885925 Sek.
3.Iteration:
- 0,0501982 Sek.
- 13.3474216 Sek.
Durchschnittlich:
- Beitritt: 0,0569367 Sek.
- Wo: 12.8251813 Sek.
Join ist 225-mal schneller
Schlussfolgerung: Vermeiden Sie, wo Beziehungen angegeben werden sollen, und verwenden Sie nach Möglichkeit JOIN (definitiv in LINQ to DataSet und Linq-To-Objects
allgemein).
Join
irgendetwas zu verwenden . Warum sollten Sie sich auf ein Optimierungsprogramm verlassen, wenn Sie den optimierten Code von Anfang an schreiben können? Es macht auch Ihre Absichten klarer. Also die gleichen Gründe, warum Sie JOIN in SQL bevorzugen sollten .