LINQ to SQL引擎盖下

时间:2013-11-05 09:37:40

标签: c# sql performance linq linq-to-sql

我知道之前已经部分问了这个问题,但没有一个问题完全回答这个问题。

当使用LINQ to SQL从数据库中检索数据时会发生什么?

我已阅读以下问题:

我不清楚的是:数据库访问的是哪一点?查询何时运行?

如果我运行以下查询,它将如何转换为SQL查询?

    DatabaseDataContext db = new DatabaseDataContext();
    var users = from x in db.Users 
                where x.Rank > 10 
                orderby x.RegistrationDate descending
                select x)
                .Skip(pageIndex * recordCount)
                .Take(recordCount);

然后,如果我尝试访问某些用户的某些属性,那么查询将如何构建(部分回答here)?

var temp = users.ToList()[0].SomeProperty;

基本上,我真正想知道的是LINQ to SQL是如何工作的,它是如何从C#语言语句到SQL以及它是如何优化的。

3 个答案:

答案 0 :(得分:6)

LINQ to SQL框架将采用您的Linq查询(实际上是表达式树),然后将此表达式树转换为纯SQL查询。见How to: Use Expression Trees to Build Dynamic Queries

事实上,每个表达式树都可以翻译成您需要的任何语言或数据库。您将有不同的提供程序为不同的数据库(OracleSQLite等)实现IQueryable。请注意,LINQ to SQL是LINQ to SQL Server的缩写。另一方面,实体框架/ LINQ to Entities可以更容易地用于其他数据库。

这里的要点是IQueryable接口,它包含一个表达式树,以及提供程序的实现。有关如何实现提供程序的示例,即如何从表达式树转换为查询,请参阅LINQ: Building an IQueryable Provider

这是一个snippet,可以让您了解幕后发生的事情:

if (select.OrderBy != null && select.OrderBy.Count > 0) 
{
    this.AppendNewLine(Indentation.Same);
    sb.Append("ORDER BY ");
    for (int i = 0, n = select.OrderBy.Count; i < n; i++) 
    {
        OrderExpression exp = select.OrderBy[i];
        if (i > 0) 
        {
            sb.Append(", ");
        }
        this.Visit(exp.Expression);
        if (exp.OrderType != OrderType.Ascending) 
        {
            sb.Append(" DESC");
        }
    }
}

答案 1 :(得分:3)

只要要求结果,就会运行查询。

var qry = (from x in db.Users where x.Rank > 10 orderby x.RegistrationDate descending
            select x)

此时查询运行,因为你没有使用结果。
将其放入foreach或将其转换为List,并且查询将被强制转换为Materiliaze。

经验法则是: 每当在IQueryable上调用GetEnumerator时,查询就会被强制进行materiliaze(对于数据库来说是真实的,并获得实际的重新开发)。

答案 2 :(得分:1)

在MSDN上关于LINQ to SQL的文章中回答了所有你想知道的事:http://msdn.microsoft.com/en-us/library/bb425822.aspx

顺便说一下,如果您只是使用结果的一部分,就像上面的代码一样,最好修改您的查询,如下所示:

var prop = (from x in db.Users 
                where x.Rank > 10 
                orderby x.RegistrationDate descending
                select x.SomeProperty)
                .Skip(pageIndex)
                .First()
                .Select(x => x);

您在查询中进行的优化通常比系统执行窥孔优化的方式更重要...