【问题标题】:LINQ performing multiple queries instead of a single "joined" queryLINQ 执行多个查询而不是单个“联合”查询
【发布时间】:2011-04-11 21:12:59
【问题描述】:

无论如何,我都不是 LINQ 高级用户,但可以在基本层面上摸索。我有一个关于 LINQ 如何制定它的查询“策略”的问题。我会尽力解释这一点,并通过记忆写一个非常愚蠢的例子。

我有一个包含多个数据库视图的数据模型。假设视图具有如下列结构:

人物视图

PersonViewId | Surname | GivenName | OtherViewId
------------------------------------------------

其他视图视图

OtherViewId | PersonViewId | Name
---------------------------------

在设置视图的主键 (PersonView.PersonViewId / OtherView.OtherViewId) 并将相应的字段设置为不可为空后,我创建了 PersonView.PersonViewId (Parent) 与 OtherView.PersonViewId (Child) 之间的关联。我将其设置为“一对一”并编写一些代码来使用它:

StringBuilder s = new StringBuilder();
foreach(PersonView p in dc.PersonViews)
{
    s.AppendLine(p.OtherViews.Name + "<br />");
}

在注意到性能极差后,我分析了数据库并注意到它正在对 foreach 语句中的每个 PersonView 进行查询。

此时,我重写了查询并将 DBML 中的关联替换为 LINQ 查询中的 JOIN,分析了数据库并按预期查询了 DB,仅一次。

我认为这与实际上正在查询数据库有关,但不确定在哪里进行调试。有人可以为我指出正确的方向,以帮助我提高使用关联的性能,还是我坚持使用 JOIN 来完成我需要的事情?

谢谢:)

【问题讨论】:

  • 您应该检查 LINQ 生成的代码。

标签: c# .net asp.net linq linq-to-sql


【解决方案1】:

这是由延迟加载引起的 - 您可以通过应用 LoadWith()(相当于 EF 的 Include() 用于 Linq to SQL)然后执行查询来解决这个问题:

var dlo = new DataLoadOptions();
dlo.LoadWith<PersonView>(p => p.OtherViews);
dc.LoadOptions = dlo;
//your query here

【讨论】:

    【解决方案2】:

    这是错误的 LINQ-2-SQL 的延迟加载(又名延迟加载)功能,当您执行 p.OtherViews.Name 时,它正在对您的 OtherViews 表进行查询。

    有两种处理方法,一种是关闭延迟加载:

    dc.DeferredLoadingEnabled = false;
    

    另一种方法是对结果中您想要的所有内容进行投影,并使用该投影:

    var people = from p in dc.PersonViews
                 select new {
                     Person = p,
                     Name = p.OtherViews.Name
                 };
    

    然后是 BrokenGlass 的建议,我直到现在才知道 :-)

    【讨论】:

      【解决方案3】:

      您看到这一点的原因是 Linq 对这些关系使用了延迟加载。换句话说,Linq 不会加载关联,直到您实际尝试使用它。

      这有助于提高性能,因为如果您并不总是需要关联,就不会执行不必​​要的 JOIN,也不会检索不需要的数据。

      如果您确定您需要数据并且它不断发出请求,它可能会损害性能。

      您可以通过保持关联不变来解决此问题,但请使用 DataLoadOptions。例如:

      var dc = new DataContext();
      dc.DeferredLoadingEnabled = false;
      
      DataLoadOptions loadOptions = new DataLoadOptions();
      loadOptions.LoadWith<PersonView>(o => o.OtherView);
      
      dc.LoadOptions = loadoptions;
      

      现在,每当您查询 PersonView 时,它都会自动加载 OtherView 关系。

      这种方法的好处是您可以在需要时打开和关闭它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多