【问题标题】:Manually select related table data (SELECT N + 1 problem) LINQ to SQL手动选择相关表数据(SELECT N+1问题)LINQ to SQL
【发布时间】:2009-08-19 10:22:35
【问题描述】:

数据库示例:

图片 - 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;
}

编辑

尝试数据加载选项后,这是一个正在生成的示例查询

{SELECT [t0].[id], [t0].[title], [t0].[图例],[t0].[添加日期], [t0].[deleted], [t0].[averageRating], [t0].[numberOfVotes], [t0].[imageOfTheWeek], [t0].[版权], [t0].[版权文本], [t0].[areaOfInterest], [t0].[typeId], [t0].[作者 ID], [t0].[编辑状态 ID], [t0].[cmets] FROM [dbo].[Image] AS [t0] 交叉连接 ([dbo].[ImageTag] AS [t1] INNER JOIN [dbo].[Tag] AS [t2] ON [t2].[id] = [t1].[TagId]) WHERE ([t2].[id] = @p0) AND (NOT ([t0].[deleted] = 1)) AND (NOT ([t0].[deleted] = 1)) AND ([t1].[ImageId] = [t0].[id]) }

【问题讨论】:

  • 添加了更新 - 尝试明确禁用延迟加载。

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


【解决方案1】:

您可以使用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;

【讨论】:

  • 我原以为会是这样,它编译得很好,但仍然会触发不需要的查询
【解决方案2】:

为什么不试试类似的东西:

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

这将返回一个只有标签名称的集合。我希望我在这里正确理解你的问题。希望对你有帮助

【讨论】:

  • 不,不太抱歉。我仍然需要返回一组图像,但我需要它已经加载了它们的标签,因此服务器不必再次查询它们
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-03
  • 2016-05-17
相关资源
最近更新 更多