我知道之前已经部分问了这个问题,但没有一个问题完全回答这个问题。
当使用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以及它是如何优化的。
答案 0 :(得分:6)
LINQ to SQL框架将采用您的Linq查询(实际上是表达式树),然后将此表达式树转换为纯SQL查询。见How to: Use Expression Trees to Build Dynamic Queries
事实上,每个表达式树都可以翻译成您需要的任何语言或数据库。您将有不同的提供程序为不同的数据库(Oracle,SQLite等)实现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);
您在查询中进行的优化通常比系统执行窥孔优化的方式更重要...