关于LINQ to SQL基础知识的问题

时间:2010-03-23 18:12:52

标签: asp.net linq-to-sql

我刚开始学习LINQ to SQL,到目前为止,我对易用性和良好性能印象深刻。

我曾经认为在进行像

这样的LINQ查询时
from Customer in DB.Customers where Customer.Age > 30 select Customer

LINQ从数据库中获取所有客户(“SELECT * FROM Customers”),将它们移动到Customers数组,然后使用.NET方法在该数组中进行搜索。这是非常低效的,如果数据库中有成千上万的客户呢?制作如此大的SELECT查询会导致Web应用程序崩溃。

现在经历了LINQ to SQL实际上的速度之后,我开始怀疑在执行该查询时我刚刚编写,LINQ以某种方式将其转换为SQL查询字符串

SELECT * FROM Customers WHERE Age > 30

只有在必要时才会运行查询。

所以我的问题是:我是对的吗?什么时候查询实际运行?

我问的原因不仅仅是因为我想了解它是如何工作的,以便构建优秀的优化应用程序,但因为我遇到了以下问题。

我有两张桌子,其中一张是书籍,另一张是有关某些日子出售的书籍数量的信息。我的目标是选择过去10天内至少每天销售50次的书籍。这是通过这个简单的查询完成的:

from Book in DB.Books where (from Sale in DB.Sales where Sale.SalesAmount >= 50 && Sale.DateOfSale >= DateTime.Now.AddDays(-10) select Sale.BookID).Contains(Book.ID) select Book

关键是,我必须在几个查询中使用检查部分,我决定创建一个包含所有流行书籍ID的数组:

var popularBooksIDs = from Sale in DB.Sales where Sale.SalesAmount >= 50 && Sale.DateOfSale >= DateTime.Now.AddDays(-10) select Sale.BookID;

但是当我现在尝试进行查询时:

from Book in DB.Books where popularBooksIDs.Contains(Book.ID) select Book

它不起作用!这就是为什么我认为我们不能在LINQ to SQL查询中使用各种快捷方式,就像我们不能在真正的SQL中使用它们一样。我们必须创建直截了当的查询,对吗?

4 个答案:

答案 0 :(得分:3)

你是对的。 LINQ to SQL确实创建了实际的SQL来检索结果。

至于您的快捷方式,有办法解决这些限制:

var popularBooksIds = DB.Sales
    .Where(s => s.SalesAmount >= 50 
        && s.DateOfSale >= DateTime.Now.AddDays(-10))
    .Select(s => s.Id)
    .ToList();

// Actually should work. 
// Forces the table into memory and then uses LINQ to Objects for the query
var popularBooksSelect = DB.Books
    .ToList()
    .Where(b => popularBooksIds.Contains(b.Id));

答案 1 :(得分:1)

是的,查询被转换为SQL字符串,并且底层SQL可能会有所不同,具体取决于您要执行的操作...因此在这方面您必须小心。签出一个名为linqpad的工具,您可以在其中尝试查询并查看正在执行的SQL。

此外,它在迭代集合或调用ToList()上的方法时运行。

答案 2 :(得分:1)

实体框架或linq查询有时会很棘手。有时你会对生成的sql查询的效率感到惊讶,有时查询是如此复杂和低效,以至于你会砸到你的额头。

最好的想法是,如果您对查询有任何疑问,请在后端运行一个sql profiler,它将监视所有进入的查询。这样您就可以确切知道传递给sql server的内容并纠正任何低效问题如果需要的话。

答案 3 :(得分:1)

http://damieng.com/blog/2008/07/30/linq-to-sql-log-to-debug-window-file-memory-or-multiple-writers

这将帮助您查看运行查询的内容和时间。此外,Damiens博客充满了其他linq to sql的善良。

您可以使用.Any方法生成EXISTS子句。我比尝试生成IN子句更成功,因为它喜欢检索所有数据并将其全部作为参数传递给查询

在linq to sql中,可以组合IQueryable表达式片段来创建单个查询,它会尽可能地保留所有内容作为IQueryable,然后再执行无法在SQL中表达的内容。当您调用ToList时,您直接要求它将该查询解析为存储在内存中的IEnumerable。

在大多数情况下,您最好不要提前选择图书ID。将流行书籍的片段保存在代码中的单个位置,并在必要时使用它,以构建另一个查询。 IQueryable只是一个表达式树,在其他一些点被解析为SQL。

如果您认为您的应用程序通过将流行书籍存储在其他位置(内存缓存或其他内容)而表现更好,那么您可以考虑事先将其删除,然后再进行检查。这意味着每个book id将作为sproc参数传入并在IN子句中使用。

相关问题