Quel est le meilleur moyen de vérifier si un objet existe dans la base de données du point de vue des performances? J'utilise Entity Framework 1.0 (ASP.NET 3.5 SP1).
Réponses
Trop de publicités?Si vous ne voulez pas exécuter SQL directement, le meilleur moyen est d'utiliser Tout(). C'est parce que les() sera de retour dès qu'il trouve une correspondance. Une autre option est de Count(), mais ce peut être nécessaire de vérifier chaque ligne avant de retourner.
Voici un exemple de comment l'utiliser:
if (context.MyEntity.Any(o => o.Id == idToMatch))
{
// Match!
}
Et dans vb.net
If context.MyEntity.Any(function(o) o.Id = idToMatch) Then
' Match!
End If
À partir d'un point de vue des performances, je suppose que c'directement la requête SQL à l'aide de la EXISTE de commande approprié. Voir ici pour savoir comment exécuter SQL directement dans le Cadre de l'Entité: http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/25/execute-t-sql-statements-in-entity-framework-4.aspx
J'ai eu à gérer un scénario où le pourcentage de doublons être fourni dans les nouveaux enregistrements de données a été très élevé, et ainsi de plusieurs milliers d'appels de base de données ont été réalisés pour contrôler les doublons (si le CPU a envoyé beaucoup de temps à 100%). En fin de compte j'ai décidé de garder la dernière de 100 000 enregistrements dans la mémoire cache. De cette façon j'ai pu vérifier les doublons à l'encontre de la mise en cache des dossiers qui a été extrêmement rapide par rapport à une requête LINQ contre la base de données SQL, puis d'écrire réellement de nouveaux enregistrements à la base de données (ainsi que les ajouter à la cache de données, que j'ai également triés et garni de garder sa longueur gérable).
Notez que les données brutes d'un fichier CSV qui contient de nombreux dossiers individuels qui devait être analysée. Les enregistrements de chaque consécutives fichier (qui est venu à un taux d'environ 1 toutes les 5 minutes) se chevauchent considérablement, par conséquent, le pourcentage élevé de doublons.
En bref, si vous avez horodaté des données brutes de venir dans, à peu près dans l'ordre, puis à l'aide d'une mémoire cache peut aider avec l'enregistrement de la duplication de vérifier.
Je sais que c’est un très vieux fil de discussion mais que si quelqu'un comme moi avait besoin de cette solution, voici ce que j’ai utilisé sur VB.NET.
Private Function ValidateUniquePayroll(PropertyToCheck As String) As Boolean
// Return true if Username is Unique
Dim rtnValue = False
Dim context = New CPMModel.CPMEntities
If (context.Employees.Any()) Then ' Check if there are "any" records in the Employee table
Dim employee = From c In context.Employees Select c.PayrollNumber ' Select just the PayrollNumber column to work with
For Each item As Object In employee ' Loop through each employee in the Employees entity
If (item = PropertyToCheck) Then ' Check if PayrollNumber in current row matches PropertyToCheck
// Found a match, throw exception and return False
rtnValue = False
Exit For
Else
// No matches, return True (Unique)
rtnValue = True
End If
Next
Else
// The is currently no employees in the person entity so return True (Unqiue)
rtnValue = True
End If
Return rtnValue
End Function
J'ai eu quelques difficultés avec mes EntityKey se compose de trois propriétés (PK avec 3 colonnes) et je n'ai pas envie de vérifier chacune des colonnes parce que ce serait moche. J'ai pensé à une solution qui fonctionne à tous les temps, avec toutes les entités.
Une autre raison pour cela est que je n'aime pas le catch UpdateExceptions à chaque fois.
Un peu de Réflexion est nécessaire pour obtenir les valeurs des propriétés de clé.
Le code est conçu comme une extension de simplifier l'utilisation:
context.EntityExists<MyEntityType>(item);
Jetez un oeil:
public static bool EntityExists<T>(this ObjectContext context, T entity)
where T : EntityObject
{
object value;
var entityKeyValues = new List<KeyValuePair<string, object>>();
var objectSet = context.CreateObjectSet<T>().EntitySet;
foreach (var member in objectSet.ElementType.KeyMembers)
{
var info = entity.GetType().GetProperty(member.Name);
var tempValue = info.GetValue(entity, null);
var pair = new KeyValuePair<string, object>(member.Name, tempValue);
entityKeyValues.Add(pair);
}
var key = new EntityKey(objectSet.EntityContainer.Name + "." + objectSet.Name, entityKeyValues);
if (context.TryGetObjectByKey(key, out value))
{
return value != null;
}
return false;
}