Home > Enterprise >  How to use Find or Find<T> on DbContext in EF?
How to use Find or Find<T> on DbContext in EF?

Time:09-17

NB I'm not asking how to find/filter entities in the DB. I'm not asking about the difference between Find and Where. I'm not asking about the implication of generics.

According to the docs, the DbContext provides methods Find and Find<T>. Usually, I go through the DbSet but noticing that there's Add() on both the context directly and the DB set, I wanted to see what will happen if I try to filter directly on the context too, instead of the DB set.

I haven't found a single example of such call, though. A lot of information on going through the DB set and the differences mentioned in the disclaimer at the top. But I see no sample showing usage of Find() nor Find<T>() directly on the context.

Is it possible at all and if so, how? Intellisense is cryptic...

CodePudding user response:

When you use Find on a DbSet, the Type of entity is known, so it just needs to Find by the provided ID.

When you use Find on the DbContext, you either have to tell EF which Type (Entity) to find against from its known mappings, or you can use the Generic version which defines the Type of entity to search against.

Why would you use these methods instead of DbSet.Find? One example would be where you don't want to expose an aspect of your domain as a DbSet. For example if you have a DbSet of Customers, Businesses, etc. that all contain references to Address entities it would be uncommon to ever need to load an Address outside of that scope so you would probably opt not to expose a DbSet<Address> in your domain to potentially be abused through convenience. In the case where your DbContext actually does need to locate a particular Address, you could use DbContext.Find<Address>(addressId) to load it.

Honestly I don't use DbContext.Find(), I don't even use DbSet.Find(), I much, much prefer to work with IQueryable and projection. But hey, it's an option. :)

CodePudding user response:

It does the same thing, but without using the DbSet. It works by specifying the type (entity) you want to fetch. You just have to specify the type, which must match your DbSet.

Is it possible at all and if so, how?

public class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> options) : base(options) { }

    public DbSet<City> Cities{ get; set; }
    public DbSet<State> States { get; set; }
}

And use it like so:

MyContext context = CreateContext() // Or inject it...

// Will return the City which have id == 5. 
object myUntypedCity = context.Find(typeof(City), 5);

// Will return the city which have id == [your guid].
City myTypedCity = context.Find<City>(Guid.NewGuid());

As a sidenote; Add() on the Context works the same way. It will detect which type of entity it is and put it on the correct DbSet. I do not know what will happen if you have several DbSet using the same type.

why we have a non-generic Find() on the context given that quite a few DBs are using integers for IDs, hence ensuring ambiguous ID values between different entities/tables

In some scenarios you might not expose the DbSet or you only know the type of the entity. This can be very handy when making some very generic code where you don't have a typed entity nor know exactly what type of id (primary key) it has. It may be a Guid or an int. I myself have never found a practical use for Find on the DbContext.

  • Related