优化LINQ to SQL查询

时间:2008-09-08 17:05:22

标签: linq linq-to-sql optimization

我有一个如下所示的查询:

public IList<Post> FetchLatestOrders(int pageIndex, int recordCount)
{
    DatabaseDataContext db = new DatabaseDataContext();
    return (from o in db.Orders
            orderby o.CreatedDate descending
            select o)
            .Skip(pageIndex * recordCount)
            .Take(recordCount)
            .ToList();
}

我需要打印订单信息和创建订单的用户:

foreach (var o in FetchLatestOrders(0, 10))
{
    Console.WriteLine("{0} {1}", o.Code, o.Customer.Name);
}

这会生成一个SQL查询,为每个订单带来订单和一个查询以带来客户。是否可以优化查询,以便将订单及其客户带入一个SQL查询?

由于

UDPATE:通过sirrocco的建议,我改变了这样的查询并且它有效。只生成一个选择查询:

public IList<Post> FetchLatestOrders(int pageIndex, int recordCount)
{
    var options = new DataLoadOptions();
    options.LoadWith<Post>(o => o.Customer);
    using (var db = new DatabaseDataContext())
    {
        db.LoadOptions = options;
        return (from o in db.Orders
                orderby o.CreatedDate descending
                select o)
                .Skip(pageIndex * recordCount)
                .Take(recordCount)
                .ToList();
    }
}

谢谢sirrocco。

3 个答案:

答案 0 :(得分:4)

你可以做的其他事情是EagerLoading。在Linq2SQL中,您可以使用LoadOptions:More on LoadOptions 关于L2S的一个非常奇怪的事情是,您只能在第一个查询发送到数据库之前设置LoadOptions。

答案 1 :(得分:0)

您可能希望使用已编译的查询

查看http://www.3devs.com/?p=3

答案 2 :(得分:0)

给出如下LINQ语句:

context.Cars
  .OrderBy(x => x.Id)
  .Skip(50000)
  .Take(1000)
  .ToList();

这大概翻译成:

select * from [Cars] order by [Cars].[Id] asc offset 50000 rows fetch next 1000 rows

由于offset和fetch是order by的扩展,因此只有在运行select-portion(google)后才会执行它们。这意味着在获取获取结果之前,会对整个数据集([Cars])执行带有大量联接语句的昂贵选择。

优化声明 所需要做的就是获取OrderBy,Skip和Take语句,并将它们放入Where-clause中:

context.Cars
  .Where(x => context.Cars.OrderBy(y => y.Id).Select(y => y.Id).Skip(50000).Take(1000).Contains(x.Id))
  .ToList();

这大概翻译成:

exec sp_executesql N'
select * from [Cars]
where exists
  (select 1 from
    (select [Cars].[Id] from [Cars] order by [Cars].[Id] asc offset @p__linq__0 rows fetch next @p__linq__1 rows only
    ) as [Limit1]
    where [Limit1].[Id] = [Cars].[Id]
  )
order by [Cars].[Id] asc',N'@p__linq__0 int,@p__linq__1 int',@p__linq__0=50000,@p__linq__1=1000

所以现在,外部选择语句仅基于where存在子句在过滤的数据集上执行!

同样,您的里程可能会因更改而节省多少查询时间。一般的经验法则是,选择语句越复杂,要进入的数据集越深,此优化就越有帮助。