Linq-to-SQL包含扩展方法不起作用

时间:2012-01-31 13:04:45

标签: c# linq linq-to-sql

我在http://damieng.com/blog/2010/05/21/include-for-linq-to-sql-and-maybe-other-providers尝试了Include扩展方法,但它并没有真正起作用。

所以我在Linq-to-SQL中有这个查询:

 var items = dataContext.Items()
            .Where(x => x.Id < 100)             
            .ToList();

并且数据上下文具有加载选项LoadWith(x => x.ItemImages)

产生这个SQL语句:

SELECT [t0].[Id], [t0].[Number], [t0].[Title], [t1].[Id] AS [Id2], [t1].[ItemId], [t1].[Url], (
SELECT COUNT(*)
FROM [dbo].[ItemImage] AS [t2]
WHERE [t2].[ItemId] = [t0].[Id]
) AS [value]
FROM [dbo].[Item] AS [t0]
LEFT OUTER JOIN [dbo].[ItemImage] AS [t1] ON [t1].[ItemId] = [t0].[Id]
WHERE [t0].[Id] < @p0
ORDER BY [t0].[Id], [t1].[Id]

现在,如果我不使用数据加载选项,但重写查询:

 var items = dataContext.Items()
            .Where(x => x.Id < 100)
            .Select(x=>new Tuple<Item, EntitySet<ItemImage>>(x, x.ItemImages))
            .AsEnumerable()
            .Select(x=>x.Item1)
            .ToList();

生成的SQL语句是相同的:

SELECT [t0].[Id], [t0].[Number], [t0].[Title], [t1].[Id] AS [Id2], [t1].[ItemId], [t1].[Url], (
SELECT COUNT(*)
FROM [dbo].[ItemImage] AS [t2]
WHERE [t2].[ItemId] = [t0].[Id]
) AS [value]
FROM [dbo].[Item] AS [t0]
LEFT OUTER JOIN [dbo].[ItemImage] AS [t1] ON [t1].[ItemId] = [t0].[Id]
WHERE [t0].[Id] < @p0
ORDER BY [t0].[Id], [t1].[Id]

但是,如果我正在访问items[0].ItemImages属性,它会请求SQL Server检索项目图像,因此看起来它有所有必需的数据以避免其他查询,但是实现出错并且它仍然存在其他查询,虽然它可以避免它们。

我可以以某种方式解决这个问题吗?

更新:我对使用LoadWith选项的性能持怀疑态度,并认为执行两个查询(一个用于项目,第二个用于图像)和代码中的映射会比Linq2Sql生成单个SQL查询更快,但至少与我的数据量单个查询的工作速度更快,因此看到解决方案会非常有趣。

1 个答案:

答案 0 :(得分:1)

我博客上的include方法仅以一对一的关系进行演示和测试。

通过投影引用一对一的查询,它填充LINQ to SQL身份缓存。稍后导航任何导航属性时,它将首先点击该缓存。

不幸的是,LINQ to SQL不够先进,不能以这种方式缓存到多个关联。

您可以选择使用LoadWith或编写项目和分组的查询,例如

var items = dataContext.ItemImages()
        .Where(x => x.Item.Id < 100)
        .Select(x => new Tuple<ItemImage, Item>(x, x.Item))
        .AsEnumerable()
        .Select(x = > x.Item1)
        .GroupBy(x => x.Item);

此查询的警告是您不会看到任何没有ItemImages的项目。