简体   繁体   English

更好地理解 Entity Framework Core 查询和 DbSet 影响

[英]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.我是 Entity Framework 的新手,想对某些事情进行一些澄清。 I understand the DbContext such as pointing to a SQL database with a connection string.我了解DbContext ,例如指向带有连接字符串的 SQL 数据库。 Within the DbContext , you declare DbSet<perEachTable> that you want / plan to expose and get data from, from said SQL database.DbContext中,您声明您希望/计划从所述 SQL 数据库公开和获取数据的DbSet<perEachTable>

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.现在,您进入 LINQ,我了解了一些链接,例如可枚举的事物列表和寻找某些符合条件的 where 条件条目。

Now, my bigger question and how EF queries.现在,我更大的问题以及 EF 如何查询。 You have a DbContext pointing to SQL Server.您有一个指向 SQL Server 的DbContext It has a table of say 250k customers.它有一张有 25 万客户的桌子。 It has its primary key defined as Id (or CustomerId ) which is expected.它的主键定义为预期的Id (或CustomerId )。 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在我看到的 LINQ 查询中,它指的是任何表的DbSet并运行 where 子句,例如

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.我的想法是整个客户列表都被从它的 DbSet 上下文中拉下来了。 Then it runs the link WHERE clause to look for email.然后它运行链接WHERE子句来查找电子邮件。 I don't think I want to be pulling down 250k customers down every time just to LINQ iterate through them.我不认为我想每次都减少 250k 客户只是为了 LINQ 迭代他们。

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.为什么WHERE实际上并没有使用整个客户数据集(尤其是当它继续增长时),只是根据可用的索引进行优化,实际上并没有把所有东西都拉下来。

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.这是否只是一个正在应用的魔法黑盒,EF 只是将符合条件的最终条目交给您(或者如果其他更开放的查询则很少)。

I have also seen instances of EF Core using fully written SQL statements and parameterized which is what I am more accustomed to doing.我还看到了使用完全编写的 SQL 语句和参数化的 EF Core 实例,这是我更习惯做的事情。 Letting the SQL Server engine return the data based on the explicit criteria that best matches qualifying indexes.让 SQL Server 引擎根据与合格索引最匹配的显式条件返回数据。

Appreciate clarification on the underlying operations.感谢对基础操作的澄清。

I'm not an expert about EF but, no not the whole table is requested.我不是 EF 方面的专家,但不要求整张桌子。

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).它不返回IEnumerable而是返回IQueryable ,它将基于 linq 语句生成 SQL 查询,并在迭代时在 sql-server 上执行它(例如 foreach 循环)。

You can get the SQL query by using:您可以使用以下方法获取 SQL 查询:

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() .您的代码DbSet<T>.Where()正在调用Queryable.Where()扩展方法,而不是Enumerable.Where()

Enumerable.Where returns an enumeration that will step through the underlying enumeration, applying the filter on each item. Enumerable.Where返回一个枚举,它将逐步遍历基础枚举,对每个项目应用过滤器。

The purpose of Queryable.Where() is very different. Queryable.Where()的目的非常不同。 It returns an IQueryable that captures a description of what you were doing.它返回一个IQueryable ,它捕获了您正在做什么的描述。 Each method helps you to build an Expression Tree , which is like a lambda function that has only been partially compiled.每种方法都可以帮助您构建一个Expression Tree ,它就像一个仅被部分编译的 lambda 函数。

An IQueryable also implements IEnumerable . IQueryable还实现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.因为您从DbSet创建了IQueryable ,所以 EF Core 将接管此编译过程。 Attempting to create an efficient sql statement and a function to convert the results into objects.试图创建一个高效的 sql 语句和一个将结果转换为对象的函数。

For efficiency, this function and sql will be cached.为了效率,这个函数和sql都会被缓存。 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. EF 将从您的query对象构造一个 SQL 查询并在服务器上执行该查询。 That way only the result of the SQL query is returned.这样只返回 SQL 查询的结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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