简体   繁体   中英

Better understanding of Entity Framework Core querying and DbSet impact

I am a newbie to Entity Framework and would like some clarification on some things. I understand the DbContext such as pointing to a SQL database with a connection string. Within the DbContext , you declare DbSet<perEachTable> that you want / plan to expose and get data from, from said SQL database.

Now, you get into LINQ, and I understand some of link such as enumerable lists of things and looking for certain qualifying where condition entries.

Now, my bigger question and how EF queries. You have a DbContext pointing to SQL Server. It has a table of say 250k customers. It has its primary key defined as Id (or CustomerId ) which is expected. You want to query and lookup a customer based on the user's email address (common type of expected query). The customer table has an index on the email.

In the LINQ queries I have seen, it is referring to the DbSet of whatever table and runs a where clause, such as

using (var context = new DBCustomers())
{
    var query = context.Customer
                       .Where(c => c.EMail == "someEMail@whereEver.com")
                       .FirstOrDefault<Customer>();
}

My mental thinking is that the entire list of customers is being pulled down from its DbSet context. Then it runs the link WHERE clause to look for email. I don't think I want to be pulling down 250k customers down every time just to LINQ iterate through them.

How is it that the WHERE does not actually use the entire dataset of customers (especially as/when it continues to grow) and just optimizes based the indexes available and does NOT actually pull everything down.

Is this just a magic black-box being applied and EF just hands you the entry (or few if other more open query) the final entries that qualified.

I have also seen instances of EF Core using fully written SQL statements and parameterized which is what I am more accustomed to doing. Letting the SQL Server engine return the data based on the explicit criteria that best matches qualifying indexes.

Appreciate clarification on the underlying operations.

I'm not an expert about EF but, no not the whole table is requested.

It doesn't return an IEnumerable but an IQueryable it will generate an SQL query based on the linq statement and executes it on the sql-server when it is iterated by (for example a foreach loop).

You can get the SQL query by using:

var query = context.Customer.Where(x => x.Id == 1);
Console.WriteLine(query.ToQueryString());

Your code DbSet<T>.Where() is calling the Queryable.Where() extension method, not Enumerable.Where() .

Enumerable.Where returns an enumeration that will step through the underlying enumeration, applying the filter on each item.

The purpose of Queryable.Where() is very different. It returns an IQueryable that captures a description of what you were doing. Each method helps you to build an Expression Tree , which is like a lambda function that has only been partially compiled.

An IQueryable also implements IEnumerable . When you start trying to enumerate the results, the expression tree is "compiled". Because you created the IQueryable from a DbSet , EF Core will take over this compilation process. Attempting to create an efficient sql statement and a function to convert the results into objects.

For efficiency, this function and sql will be cached. Each time you try to compile the same expression, most of the compilation process will be skipped.

EF will construct a SQL query from your query object and execute that on the server. That way only the result of the SQL query is returned.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM