62 votes

Moyen générique de vérifier si l'entité existe dans Entity Framework?

Similaire à la Meilleure façon de vérifier si l'objet existe dans le Cadre de l'Entité?

Je suis à la recherche d'une méthode générique permettant de vérifier la présence d'une entité dans un DbSet. Quelque chose de ce genre, qui ne fonctionne pas:

private DbContext DbContext { get; set; }

private DbSet<T> DbSet { get; set; }

public Boolean Exists(T entity) {
    return ((from item in this.DbSet
             where item == entity
             select item).Count() > 0);
}

La ligne where item == entity travaille dans LINQ to SQL, mais apparemment pas avec LINQ to entities. Puisque les entités peuvent avoir différentes touches je ne peux pas les avoir tous hériter d'une commune abstrait avec une clé à des fins de comparaison.

J'ai pu faire cela, mais je suis inquiet au sujet de la performance d'attraper les exceptions, comme un processus de vérification de Ce qui ne fonctionne pas depuis aussi longtemps que l'entité est détachée de l' OriginalValues de la propriété ne peuvent pas être obtenues:

public Boolean Exists(T entity) {
    try {
        var current = this.DbContext.Entry(entity).OriginalValues;
        // Won't reach this line if the entity isn't in the database yet
        return true;
    }
    catch (Exception ex) {
        return false;
    }
}

96voto

Ladislav Mrnka Points 218632

Voulez-vous générique façon de vérifier si l'entité a été chargé par le contexte ou générique façon d'interroger la base de données si l'entité existe?

Pour le premier cas d'utilisation:

public bool Exists<T>(T entity)
{
    return this.Set<T>().Local.Any(e => e == entity);
}

Pour le dernier cas d'utilisation (il va vérifier chargé des entités en tant que bien):

public bool Exists<T>(params object[] keys)
{
    return (this.Set<T>().Find(keys) != null);
}

Edit:

EF premier code n'est pas censé accès à ce genre d'informations, mais il est possible d'obtenir le nom de l'entité clés. Je pense que quelque chose comme ça devrait fonctionner:

var objContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var keyNames = objSet.EntitySet.ElementType.KeyMembers.Select(m => m.Name);

Mais tout cela ne fait pas de sens. Vous souhaitez approche générique, mais votre entités ne partage pas les informations nécessaires pour permettre approche générique. Maintenant tu dis que tu ne sais même pas de valeurs de clé. L'utilisation de ce "générique" exigera la réflexion et le manuel de construction de l'arborescence d'expression.

20voto

Yuck Points 23174

Merci à @Ladislav de m'avoir mis dans la bonne direction. Voici le code pour une méthode générique Exists() .

Je voudrais noter que cela ne nécessite pas de réflexion et semble très bien performer. La seule chose qui ne me passionne pas, c'est que TryGetObjectByKey() a pour effet secondaire de lier l'entité trouvée. Puisque je ne veux pas que Exists() ait ce résultat non intentionnel, je dois détacher l'entité si elle a été trouvée.

 public Boolean Exists(T entity) {
    var objContext = ((IObjectContextAdapter)this.DbContext).ObjectContext;
    var objSet = objContext.CreateObjectSet<T>();
    var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);

    Object foundEntity;
    var exists = objContext.TryGetObjectByKey(entityKey, out foundEntity);
    // TryGetObjectByKey attaches a found entity
    // Detach it here to prevent side-effects
    if (exists) {
        objContext.Detach(foundEntity);
    }

    return (exists);
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X