我使用使用以下代码从数据库中查询数据:
CamicDbContext context = new CamicDbContext();
public override object Read(DataManagerRequest dm, string key = null)
{
IQueryable<Country> query = context.Set<Country>();
query = query.Where(x => x.IsDeleted == false);
query = query.Where(x => x.Code == "PT");
int count = query.Cast<Country>().Count();
return dm.RequiresCounts ? new DataResult() { Result = query, Count = count } : (object)query;
}当声明query变量时,它似乎正在获取表中的所有项(图1),这似乎是错误的,因为它对较大的实体没有效率;因此,我想在不获取数据的情况下初始化变量,构建查询,然后只有在到达return query时才执行查询,这样服务器才会查询和返回匹配过滤器的项。
我尝试过多种解决方案。这个程序-- Creating dynamic queries with Entity Framework --接近于我想要实现的目标,但是它中的代码具有与我前面提到的相同的效果。我.我错过了什么用延期执行的方法吗?
我处决了
IQueryable<Country> query = context.Set<Country>();结果视图显示了表中的所有264项:

发布于 2021-12-30 15:37:08
当声明查询变量时,它似乎正在获取表中的所有项(图1),
不是这样的
,我--我--我错过了使用延迟执行的东西吗?
你才是
这是一个测试应用程序的屏幕截图,在我打开登录之后。在测试应用程序的代码中,我创建一个上下文,构建一个查询,并运行它。事实上有几次..。

x是上下文。如果我打开调试器并展开调试器工具提示中的Orders“表”,在底部有一条消息说,查看结果将枚举可枚举的。如果我枚举,那么SQL将被执行:

这上面没有任何子句--我们枚举Orders,它代表整个表,因此SQL实际上是SELECT * FROM Orders。在我的Orders测试表中没有任何数据,这就是为什么在枚举完成后我们会看到“无结果”,但是如果有1000个订单,调试器工具提示将在
下一行代码运行LINQ Where

这实际上没有执行任何SQL,但它提供了一个子句,EF可以将其转换为SQL,因此,如果您查看由DebugView返回的IQueryable的Where属性,您可以看到EF将在运行时形成的SQL (...WHERE Ref = '')。
枚举queryable实际上将运行SQL。在调试器中调用结果视图将枚举,就像在查询中执行诸如ToArray、ToList、ToDictionary (内部它们都枚举),甚至是普通的旧foreach等等一样。每当有枚举时,它就会触发SQL的运行。
如果您使用类似于先使用、计数、然后单独使用的方法,也会触发SQL查询的执行;它们不枚举整个集合,它们修改正在运行的SQL,但它们确实会导致执行。
..which把我带到了在评论中提出的观点。
我编写的代码使EF能够使用WHERE子句形成查询,但随后它要求DB执行两次:一次是获取计数(调用.Count导致SELECT COUNT(*) ... WHERE ..),另一次是获取实际数据项(调用ToList会执行一个选择列.其中...`):

假设您必须在枚举期间检索例如100项,则更有意义的是检索所有项,然后获取它们的本地计数;如果您已经将它们存储在列表中,则列表将跟踪计数。
请记住,当您正在处理EF的集合时,您还没有做任何事情来枚举它们,那么queryable您将传递并调用基本上是SQL (或部分构建的SQL )的操作,并且每次您对它做一些传递数据的操作时,它都会运行SQL。
发布于 2021-12-30 14:57:33
LINQ可以通过以下两种方式之一执行:立即执行或延迟执行。立即执行意味着读取数据源,并在声明查询的代码中执行操作。返回单个非枚举结果的所有标准查询运算符都会立即执行作为延迟的执行,这基本上意味着操作不会在声明查询的代码中执行。只有在枚举查询变量时才执行此操作。
在调试时使用和查看IQueryable将充当立即执行查询的作用,从而将该查询带入内存。在非调试环境中,这不会发生,查询将充当延迟的查询执行,这意味着一旦Count()方法被调用,它实际上将被执行。
有关按执行方式对标准查询运算符进行分类的更多信息,请参见- https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/classification-of-standard-query-operators-by-manner-of-execution
发布于 2021-12-30 16:50:34
请参阅https://weblogs.asp.net/zeeshanhirani/using-asqueryable-with-linq-to-objects-and-linq-to-sql
1.当您使用AsQueryable运算符时,允许进一步的转换:过滤、排序或聚合2。附加的lambda语句被转换为表达式树。我使用lambda函数演示表达式过滤器。3.如果在不实现AsQueryable且只实现IEnumerable< T >的查询上使用IEnumerable<运算符,则应用于查询的任何转换都会自动返回IEnumerable规范。4.如果将IQueryable推迟到调用foreach并计算表达式树时
Product[] products =
{
new Product {ProductId=1, Name="Kayak",Category="Watersports",Price=275m, Company=new Company{ CompanyName="Abc Corp",States=new String[]{"Ut","Id" } } },
new Product {ProductId=2, Name="Lifejacket", Category="Watersports",Price=48.95m, Company=new Company{ CompanyName="X Corp",States=new String[]{"Ca","Az" } }},
new Product {ProductId=3, Name="Soccer Ball", Category="Soccer",Price=19.50m, Company=new Company{ CompanyName="Y Corp",States=new String[]{"Tx","Wa" } }},
new Product {ProductId=4, Name="Corner Flag", Category="Soccer",Price=34.95m, Company=new Company{ CompanyName="Z Corp",States=new String[]{"Co","Wy" } }}
};
Transaction[] transactions =
{
new Transaction{ Name ="Bob Smith", ProductId=1, Cost=10.95M, Quantity=10},
new Transaction{ Name ="Dan Brown", ProductId=3, Cost=5.99M, Quantity=1}
};
IQueryable<Product> query = products.AsQueryable<Product>();
Expression<Func<Product, bool>> filter = x => x.Price > 100;
query = query.Where(filter);
int count = query.Cast<Product>().Count();
var result = query.Join(transactions,
product => new { product.ProductId },
transaction => new { transaction.ProductId },
(product, transaction) =>
new
{
CustomerName = transaction.Name,
ProductName = product.Name,
CompanyName = product.Company.CompanyName,
Price = product.Price
}) ;
foreach (var item in result)
{
_output.WriteLine($"Count: {count} Company: {item.CompanyName} Customer: {item.CustomerName} Product : {item.ProductName} Price : {String.Format("{0:C}", item.Price)}");
}https://stackoverflow.com/questions/70532857
复制相似问题