2010-11-17 42 views
1

我发现this link这解释了我的问题,并有一个答案,但似乎无法使其工作。LinqToSQL查询loadwith性能

下面是我对DataLoadOptions:

 options.LoadWith<Support>(p => p.PostBase); 
     options.LoadWith<Support>(p => p.PostMaterial); 
     options.LoadWith<Support>(p => p.PostPosition); 
     options.LoadWith<Support>(p => p.PostSize); 
     options.LoadWith<Support>(p => p.PostType); 
     options.LoadWith<Support>(p => p.Signs); 
     options.LoadWith<Support>(p => p.SupportComments); 
     options.LoadWith<Support>(p => p.SupportInspections); 
     options.LoadWith<Support>(p => p.SupportPhotos); 
     options.LoadWith<Sign>(p => p.SignBacking); 
     options.LoadWith<Sign>(p => p.SignComments); 
     options.LoadWith<Sign>(p => p.SignCondition); 
     options.LoadWith<Sign>(p => p.SignDelineator); 
     options.LoadWith<Sign>(p => p.SignFace); 
     options.LoadWith<Sign>(p => p.SignIllumination); 
     options.LoadWith<Sign>(p => p.SignToSignObstructions); 
     options.LoadWith<Sign>(p => p.UniformTrafficControlCode); 
     options.LoadWith<SignToSignObstruction>(p => p.SignObstruction); 

我认为这会给我的对象图的一个很好的解释。我试图查询符合特定搜索条件的支持对象(也许有人希望支持帖子类型的等等)。

如果我尝试只返回所有支持,我得到约2200支持,它需要17k查询。

我试图在另一个问题中提到的分组解决方案,但我想知道如果我做错了,或者我的情况太复杂。我删除了搜索条件,并试图返回所有支持。这导致约21k查询并拉回约3000支持。这里是我的查询:

   var group = 
       from support in roadDataContext.Supports 
       join sign in roadDataContext.Signs on support.SupportID equals sign.SupportID 
       group sign by sign.Support 
       into signGroup 
       select signGroup; 

我只是想念一些简单的东西吗?谢谢。

+0

你为什么试图在搜索查询中取回所有数据*? *您找到*您正在寻找的'Support'后,您应该使用'LoadWith'。如果你实际上需要返回一个非规范化的表作为你的搜索结果的一部分,你应该使用'Select'运算符并返回一个'x => new {x.PostBase.XXX等}显示。还要考虑分页 - 无论您如何获取数据,3000行都不合适。 – 2010-11-17 18:53:59

+0

我会再次从头开始:如果删除所有LoadWith,会发生什么情况:当时正在生成的SQL是什么?之后开始调整 – Pleun 2011-02-22 17:59:44

回答

2

我们在L2S数据层中犯了同样的错误。我们的负载选项在某些情况下是荒谬的。这是一个艰难的教训。

这被称为SELECT N + 1问题。 1为父实体,N为正被加载的关联实体的数量。你会希望L2S能够足够聪明,并且可以在一个巨大的查询中得到它,但不幸的是并非如此。它会创建一个巨大的查询,告诉它要加载的关联的ID,然后逐个检索这些关联。

也许最好的解决方法是使用投影,以便您的LINQ查询返回一个新对象,而不是一个实体。例如:

var fooDtos = from foo in db.Foo 
       where foo.bar == "What a great example" 
       select new fooDTO { FooName = foo.Name, FooBar = foo.Bar }; 

该查询返回一个IEnumerable < FooDTO>代替的IQueryable <美孚>。这有两个好处。首先你要指定L2S专门检索哪些列,所以它不会执行SELECT *。此外,您不再需要DataLoadOptions,因为您可以在查询中查询您想要的任何表并从任何表中选择以生成DTO。