Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Way to Check If Entity Exists In Entity Framework?

Similar to Best way to check if object exists in Entity Framework?

I'm looking for a generic way to check for an entity in a DbSet. Something like this, which doesn't work:

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

The line where item == entity works in LINQ to SQL, but apparently not with LINQ to Entities. Since the entities may have different keys I can't have them all inherit from a common abstract with a known key for comparison.

I could do this, but I'm worried about the performance of catching exceptions as a verification process This doesn't work either since as long as the entity is detached the OriginalValues property can't be obtained:

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;     } } 
like image 239
Yuck Avatar asked May 16 '11 14:05

Yuck


People also ask

How do I know if I have Entity Framework?

Another way to get the EF version you are using is to open the Package Manager Console (PMC) in Visual Studio and type Get-Package at the prompt. The first line with be for EntityFramework and list the version the project has installed.

How do I use Find in Entity Framework?

The Find method on DbSet uses the primary key value to attempt to find an entity tracked by the context. If the entity is not found in the context then a query will be sent to the database to find the entity there. Null is returned if the entity is not found in the context or in the database.

What is Entitystate in Entity Framework?

EF API maintains the state of each entity during its lifetime. Each entity has a state based on the operation performed on it via the context class. The entity state represented by an enum System. Data.

Is entity framework connected or disconnected?

There are 2 ways (connected and disconnected) when persisting an entity with the Entity Framework. Both ways have their own importance. In the case of a connected scenario the changes are tracked by the context but in the case of a disconnected scenario we need to inform the context about the state of the entity.


2 Answers

Do you want generic way to check if entity was loaded by context or generic way to query database if entity exists?

For the former case use:

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

For the latter case use (it will check loaded entities as well):

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

Edit:

EF code first is not supposed to access this kind of information but it is possible to get name of entity keys. I think something like that should work:

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

But this all doesn't make sense. You want generic approach but your entities doesn't share necessary information to allow generic approach. Now you say that you even don't know key values. Using this "generic" approach will require reflection and manual building of expression tree.

like image 54
Ladislav Mrnka Avatar answered Sep 24 '22 06:09

Ladislav Mrnka


Thanks to @Ladislav for getting me in the right direction. Here's the code for a generic Exists() method.

I'd like to note that this doesn't require reflection and seems to perform quite well. The only thing I'm not thrilled about is that TryGetObjectByKey() has the side-effect of attaching the found entity. Since I don't want Exists() to have that unintentional result I have to detach the entity if it was found.

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); } 
like image 39
Yuck Avatar answered Sep 21 '22 06:09

Yuck