59 votos

Forma genérica para Comprobar Si la Entidad Existe En Entity Framework?

Similar a la Mejor manera de comprobar si el objeto existe en el Marco de la Entidad?

Estoy buscando una forma genérica para comprobar la existencia de una entidad en un DbSet. Algo como esto, que no funciona:

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 línea where item == entity obras en LINQ to SQL, pero al parecer no con LINQ to entities. Dado que las entidades pueden tener diferentes teclas no puedo tener a todos ellos heredan de una abstracta común con un conocido clave para la comparación.

Yo podría hacer esto, pero estoy preocupado por el rendimiento de captura de excepciones como un proceso de verificación Esto no funciona, ya que mientras la entidad se separa de la OriginalValues de la propiedad no se puede obtener:

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;
    }
}

88voto

Ladislav Mrnka Puntos 218632

¿Quieres forma genérica para comprobar si la entidad se ha cargado por el contexto o la forma genérica para consulta de base de datos, siempre que la entidad existe?

Para el primer caso de uso:

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

Para el último caso de uso (se comprobará cargado entidades así):

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

Editar:

EF code first no se supone que el acceso a este tipo de información, pero es posible obtener el nombre de claves de entidad. Creo que algo así debería funcionar:

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

Pero todo esto no tiene sentido. Desea enfoque genérico, pero las entidades no compartir la información necesaria para permitir el enfoque genérico. Ahora usted dice que usted no sabe los valores de la clave. A través de este "genérico" enfoque requerirá la reflexión y el manual de construcción de árbol de expresión.

21voto

Yuck Puntos 23174

Gracias a @Ladislav para meterme en la dirección correcta. Aquí está el código para un genérico Exists() método.

Me gustaría señalar que esto no requiere de la reflexión y parece funcionar bastante bien. La única cosa que no me emociona es que TryGetObjectByKey() tiene el efecto secundario de fijación de la entidad. Ya no quiero Exists() tener ese resultado no intencionado tengo que separar de la entidad, si se ha encontrado.

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);
}

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X