J'ai le code suivant (la base de données est SQL Server Compact 4.0):
Dim competitor=context.Competitors.Find(id)
Lorsque je présente ce profil, la méthode Find prend 300 + ms pour récupérer le concurrent à partir d'une table de seulement 60 enregistrements.
Lorsque je change le code en:
Dim competitor=context.Competitors.SingleOrDefault(function(c) c.ID=id)
Ensuite, le concurrent se retrouve en seulement 3 ms.
La classe Concurrent:
Public Class Competitor
Implements IEquatable(Of Competitor)
Public Sub New()
CompetitionSubscriptions = New List(Of CompetitionSubscription)
OpponentMeetings = New List(Of Meeting)
GUID = GUID.NewGuid
End Sub
Public Sub New(name As String)
Me.New()
Me.Name = name
End Sub
'ID'
Public Property ID As Long
Public Property GUID As Guid
'NATIVE PROPERTIES'
Public Property Name As String
'NAVIGATION PROPERTIES'
Public Overridable Property CompetitionSubscriptions As ICollection(Of CompetitionSubscription)
Public Overridable Property OpponentMeetings As ICollection(Of Meeting)
End Class
J'ai défini les relations plusieurs à plusieurs pour CompetitionSubscriptions
et OpponentMeetings
à l'aide de l'API couramment.
La propriété ID de la classe Competitor
est un Long qui est traduit par Code First dans une colonne Identity avec une clé primaire dans le datatable (SQL Server Compact 4.0)
Qu'est-ce qui se passe ici??
Find
appelle DetectChanges
en interne, SingleOrDefault
(ou généralement n'importe quelle requête) ne le fait pas. DetectChanges
est une opération coûteuse, c'est pourquoi Find
est plus lent (mais il peut devenir plus rapide si l'entité est déjà chargée dans le contexte car Find
n'exécuterait pas requête mais juste renvoyer l'entité chargée).
Si vous souhaitez utiliser Find
pour un grand nombre d'entités - dans une boucle par exemple - vous pouvez désactiver la détection automatique des modifications comme cela (vous ne pouvez pas l'écrire en VB, donc un exemple C #):
try
{
context.Configuration.AutoDetectChangesEnabled = false;
foreach (var id in someIdCollection)
{
var competitor = context.Competitors.Find(id);
// ...
}
}
finally
{
context.Configuration.AutoDetectChangesEnabled = true;
}
Maintenant, Find
n'appellera pas DetectChanges
à chaque appel et il devrait être aussi rapide que SingleOrDefault
(et plus rapide si l'entité est déjà attachée au contexte).
La détection automatique des modifications est un sujet complexe et quelque peu mystérieux. Une grande discussion détaillée se trouve dans cette série en quatre parties:
(Lien vers la partie 1, les liens vers les parties 2, 3 et 4 sont au début de cet article)
http://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/