Manera genérica de verificar si la entidad existe en Entity Framework

¿Es similar a la mejor forma de verificar si el objeto existe en Entity Framework?

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

 private DbContext DbContext { get; set; } private DbSet 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 funciona en LINQ to SQL, pero aparentemente no con LINQ to Entities. Dado que las entidades pueden tener claves diferentes, no puedo permitir que todas hereden de un resumen común con una clave conocida para la comparación.

Podría hacer esto, pero estoy preocupado por el rendimiento de capturar excepciones como un proceso de verificación. Esto tampoco funciona, ya que mientras la entidad esté separada, no se puede obtener la propiedad OriginalValues :

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

¿Desea una forma genérica de verificar si la entidad se cargó por contexto o de forma genérica para consultar la base de datos si la entidad existe?

Para el primer uso del caso:

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

Para el último uso del caso (también verificará las entidades cargadas):

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

Editar:

En primer lugar, se supone que el código EF no tiene acceso a este tipo de información, pero es posible obtener el nombre de las claves de entidad. Creo que algo así debería funcionar:

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

Pero todo esto no tiene sentido. Desea un enfoque genérico, pero sus entidades no comparten la información necesaria para permitir un enfoque genérico. Ahora dices que incluso no sabes los valores clave. El uso de este enfoque “genérico” requerirá la reflexión y la construcción manual del árbol de expresiones.

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

Me gustaría señalar que esto no requiere reflexión y parece funcionar bastante bien. Lo único que no me entusiasma es que TryGetObjectByKey() tiene el efecto secundario de adjuntar la entidad encontrada. Como no quiero que Exists() tenga ese resultado involuntario, tengo que separar la entidad si se encontró.

 public Boolean Exists(T entity) { var objContext = ((IObjectContextAdapter)this.DbContext).ObjectContext; var objSet = objContext.CreateObjectSet(); 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); }