LINQ to SQL手动选择相关的表数据(SELECT N + 1问题)

时间:2009-08-19 10:22:36

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

数据库示例:

图片 - ImageTag - 代码

图片可以有多个标签。这些关系设置得很好,但是我遇到了性能问题。

我有许多不同的查询,根据不同的标准选择图像。它们工作正常,但是这些查询不会选择标签的数据。

这意味着如果我遍历10个图像的列表并尝试访问其标记对象(通过ImageTag),则会在我的数据库中为每个图像执行新查询。

<%foreach (LINQRepositories.Image i in Model)
  { %>

   <li><%=i.title%>
    <ul>
        <%foreach(ImageTag t in i.ImageTags){ %>
            <li><%=t.Tag.name%></li>
        <%} %>
    </ul>
   </li> 

<%} %>

这显然不太理想。有没有办法强制LINQ to SQL查询某些数据?

以下是我的一个查询示例

public static IQueryable<Image> WithTags(this IQueryable<Image> qry, IEnumerable<Tag> tags)
{
    return
        from i in qry
        from iTags in i.ImageTags
        where tags.Contains(iTags.Tag)
        select i;
}

修改

尝试dataload选项后,这是一个生成的示例查询

  

{SELECT [t0]。[id],[t0]。[title],   [t0]。[图例],[t0]。[dateAdded],   [t0]。[删除],[t0]。[averageRating],   [T 0]。[numberOfVotes]   [T 0]。[imageOfTheWeek]   [T 0]。[著作权]   [T 0]。[copyrightText]   [t0]。[areaOfInterest],[t0]。[typeId],   [T 0]。[AUTHORID]   [T 0]。[editorialStatusId]   [t0]。[评论]来自[dbo]。[图片] AS   [t0] CROSS JOIN([dbo]。[ImageTag] AS   [T1]       INNER JOIN [dbo]。[Tag] AS [t2] ON [t2]。[id] = [t1]。[TagId])WHERE   ([t2]。[id] = @ p0)AND(不是   ([t0]。[删除] = 1))和(不   ([t0]。[删除] = 1))AND   ([t1]。[ImageId] = [t0]。[id])}

2 个答案:

答案 0 :(得分:4)

您可以使用DataLoadOptions类通过查询加载相关对象。

DataLoadOptions dlo = new DataLoadOptions();

dlo.LoadWith<Image>(image => image.ImageTags);
dlo.LoadWith<ImageTag>(imageTag => imageTag.Tags);

context.DataLoadOptions = dlo;

提一下 - 这被称为“SELECT N + 1问题”

<强>更新

我通常使用LINQ to Entities并且没有太多使用LINQ to SQL的经验。可能还需要明确禁用DeferredLoadingEnabled

context.DeferredLoadingEnabled = false;

答案 1 :(得分:0)

为什么不试试像:

return
        from i in qry
        from iTags in i.ImageTags
        where tags.Contains(iTags.Tag)
        select new { TagName = i.Tag.name };

这将返回仅包含标签名称的Collection。我希望我能在这里正确理解你的问题。希望它有所帮助