2011-04-11 64 views
3

我不是任何方式的LINQ高级用户,但可以在基本级别上摸索我的方式。我有一个关于LINQ如何表达它的查询“策略”的问题。我会尽我所能解释这一点,并通过记忆写出一个非常愚蠢的例子。LINQ执行多个查询而不是单个“已加入”查询

我有一个包含多个数据库视图的数据模型。比方说,有意见一栏结构如下:

PersonView

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

奥瑟维尤查看

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

设置主键的视图后(PersonView.PersonViewId/OtherView.OtherViewId)和设置适当的字段是非可变的,我创建一个PersonView.PersonViewId(父)与OtherView.PersonViewId(Child)之间的关联。我将其设置为“一对一”,并写一些代码来使用它:

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

注意到性能极差,我异型数据库,发现它在foreach做一个查询每个PersonView年代声明。

此时我重新编写了查询,并用LINQ查询中的JOIN替换了DBML中的关联,对数据库进行了概要分析,并且按预期查询了数据库,只查询了一次。

我认为这是与事实,然后数据库实际上被查询,但不知道该在哪里调试。有人能指出我在这方面的正确方向,以帮助我提高使用关联的性能,还是我坚持使用JOIN来完成我所需要的功能?

谢谢:)

+0

您应该检查由LINQ生成的代码。 – 2011-04-11 21:15:39

回答

4

这是由延迟加载造成的 - 你可以得到解决,通过应用LoadWith()(EF的Include()对LINQ的相当于SQL),然后做查询算账:

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

这是延迟加载LINQ-2-SQL的过错,中(又名延迟加载)功能,当你在你的OtherViews表做p.OtherViews.Name它做一个查询。

有一对夫妇的方式来对付它,一个是关断延迟加载:

dc.DeferredLoadingEnabled = false; 

另一种是让你在你的结果想要的一切的投影,并使用投影:

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

再有就是BrokenGlass的建议下,我不知道到现在为止:-)

1

你看到这种情况的原因是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关系。

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