简体   繁体   English

LINQ执行多个查询而不是单个“加入”查询

[英]LINQ performing multiple queries instead of a single “joined” query

I am not a LINQ power user by any means, but can fumble my way around on a basic level. 无论如何我不是LINQ高级用户,但可以在基本级别上摸索。 I have a question regarding how LINQ formulates it's query "strategy". 我有一个关于LINQ如何制定它的查询“策略”的问题。 I will try to explain this as best as I can and write an extremely dumbed-down example by memory. 我将尝试尽可能地解释这一点,并通过记忆写出一个非常愚蠢的例子。

I have a data model that contains multiple database views. 我有一个包含多个数据库视图的数据模型。 Let's say the views have a column structure as follows: 假设视图的列结构如下:

PersonView PersonView

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

OtherView View 其他视图

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

After setting the primary keys for the view (PersonView.PersonViewId / OtherView.OtherViewId) and setting the appropriate fields to be non-nulable, I create an association between PersonView.PersonViewId (Parent) to OtherView.PersonViewId (Child). 在设置视图的主键(PersonView.PersonViewId / OtherView.OtherViewId)并将相应的字段设置为非nulable之后,我在PersonView.PersonViewId(Parent)与OtherView.PersonViewId(Child)之间创建了一个关联。 I set it to be "one to one" and write some code to consume it: 我将它设置为“一对一”并编写一些代码来使用它:

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

After noticing extremely poor performance, I profiled the database and noticed it was doing a query for each of the PersonView's in the foreach statement. 在注意到性能极差之后,我对数据库进行了分析,发现它正在对foreach语句中的每个PersonView进行查询。

At this point I rewrote the query and replaced the association in the DBML with a JOIN in the LINQ query, profiled the database and it queried the DB as expected, only once. 此时,我重新编写了查询,并在DBML中将关联替换为LINQ查询中的JOIN,对数据库进行了分析,并按预期查询了数据库,仅查询一次。

I am thinking that it is something to do with then the DB is actually being queried, but am not sure where to be debugging that. 我认为这与某些事情有关,然后实际上正在查询数据库,但我不确定在哪里进行调试。 Can someone point me in the proper direction on this to help me improve the performance of using associations or am I stuck using JOIN's to accomplish what I need? 有人能指出我正确的方向,以帮助我提高使用协会的表现,还是我坚持使用JOIN来完成我需要的东西?

Thanks :) 谢谢 :)

This is caused by lazy loading - you can get around that by applying LoadWith() (the equivalent of EF's Include() for Linq to SQL) and then doing your query afterwards: 这是由延迟加载引起的 - 你可以通过应用LoadWith() (相当于Linq到SQL的EF的Include() )然后再进行查询来解决这个问题:

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

It's the lazy-loading (aka Deferred Loading) feature of LINQ-2-SQL at fault, when you do p.OtherViews.Name it's doing a query on your OtherViews table. 这是LINQ-2-SQL的延迟加载(也称为延迟加载)功能,当你执行p.OtherViews.Name它正在对OtherViews表进行查询。

There's a couple of ways to deal with it, one is to turn-off Deferred Loading: 有几种方法可以解决它,一种是关闭延迟加载:

dc.DeferredLoadingEnabled = false;

Another is to make a projection of everything you want in your results, and use the projection: 另一种方法是在结果中投射您想要的所有内容,并使用投影:

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

And then there's BrokenGlass's suggestion, which I didn't know about until now :-) 然后是BrokenGlass的建议,直到现在我都不知道:-)

The reason you're seeing this is Linq uses deferred loading for those relationships. 你看到这个的原因是Linq对这些关系使用延迟加载。 In other words, Linq won't load the association until you actually try and use it. 换句话说,在您真正尝试使用它之前,Linq不会加载关联。

This can help performance because if you don't always need the association, you aren't performing the unnecessary JOIN, and you aren't retrieving data that you don't need. 这可以帮助提高性能,因为如果您不总是需要关联,则不会执行不必​​要的JOIN,也不会检索不需要的数据。

It can hurt performance though if your certain you need the data, and it keeps making requests. 如果您确定需要数据,它会影响性能,并且它会继续发出请求。

You can get around this by keeping your association as it was, but use DataLoadOptions. 您可以通过保持关联原样来解决这个问题,但请使用DataLoadOptions。 For example: 例如:

var dc = new DataContext();
dc.DeferredLoadingEnabled = false;

DataLoadOptions loadOptions = new DataLoadOptions();
loadOptions.LoadWith<PersonView>(o => o.OtherView);

dc.LoadOptions = loadoptions;

Now, any time you query a PersonView, it will automatically load the OtherView relationship. 现在,无论何时查询PersonView,它都会自动加载OtherView关系。

The nice thing about this approach is you can turn it on and off when you need it. 这种方法的好处是你可以在需要时打开和关闭它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM