2017-04-13 46 views
2

我有一些相关的对象和关系就像是实体框架LINQ从LastOrDefault父母发现子项目

public class Project 
{ 
    public List<ProjectEdition> editions; 
} 

public class ProjectEdition 
{ 
    public List<EditionItem> items; 
} 

public class EditionItem 
{ 

} 

我想只为每个项目

取从ProjectEditions的最后条目EditionItems

项目#1 - >版#1包含几个版项目],版#2包含几版物品]

项目#2 - >版#1 ,版本#2和版本#3

我的必需输出仅包含项目#1的版本#2和项目#2的版本#3的版本项目。我的意思是EditionItems从最新版项目的项目或最后一版的唯一

为了得到这个我想这个查询

List<EditionItem> master_list = context.Projects.Select(x => x.ProjectEditions.LastOrDefault()) 
             .SelectMany(x => x.EditionItems).ToList(); 

但在LatsOrDefault其将返回错误()部分

的例外在EntityFramework.SqlServer.dll中发生类型'System.NotSupportedException',但未在用户代码中处理

附加信息:LINQ to Entities无法识别方法'---------。Models.ProjectEdition LastOrDefault [临jectEdition(System.Collections.Generic.IEnumerable`1

所以,我怎么可以过滤项目的最后一版,然后得到一个LINQ呼叫从中EditionItems列表

+0

按相反顺序排序并获得'FirstOrDefault()' – trailmax

+1

正如您的例外所述,您的提供程序不支持'LastOrDefault()'。如果你仔细想想,如果没有应用排序顺序,当你使用SQL术语“last”时没有意义,因为记录可能来自服务器而没有特定的顺序。 – trailmax

+0

那我怎么能达到相同的?我正在使用SQL Server实体框架模型 –

回答

-1
from p in context.project 
from e in p.projectEdition.LastOrDefault() 
select new EditionItem 
{ 
    item1 = e.item1 
} 

请尝试这

2
List<EditionItem> master_list = context.Projects 
           .Select(p => p.editions.LastOrDefault()) 
           .SelectMany(pe => pe.items).ToList(); 

IF LastOrDefault不支持,你可以尝试使用OrderByDescending

List<EditionItem> master_list = context.Projects 
       .Select(p => p.editions.OrderByDescending(e => e.somefield).FirstOrDefault()) 
       .SelectMany(pe => pe.items).ToList(); 
+0

你可以尝试使用OrderByDescending,p.editions.OrderByDescending()。FirstOrDefault()? –

+0

@JibinMathew,同时检查确认你的context.Projects返回IEnumerable,所以试试使用context.Projects.AsEnumerable()。Select()。 –

+0

向下投票与有用的意见帮助! –

2

呦你不能使用方法LastOrDefault()Last()如讨论here

Insetad,您可以使用OrderByDescending()FirstOrDefault()一起使用,但首先您需要拥有一个您需要订购实体的物业ProjectEdition。例如。如果ProjectEdition有一个属性Id(其中有它的好机会),你可以使用下面的LINQ查询:

List<EditionItem> master_list = context.Projects.Select(
        x => x.ProjectEditions 
         .OrderByDescending(pe => pe.Id) 
         .FirstOrDefault()) 
         .SelectMany(x => x.EditionItems).ToList(); 
2

格兰尼特得到正确的答案,所以我不会重复他的代码。我想补充这种行为的原因。实体框架是神奇的(有时太神奇了),但它仍然将您的LINQ查询转换为SQL,并且存在底层数据库可以执行的操作(本例中为SQL Server)的限制。

当您拨打context.Projects.FirstOrDefault()时,它被翻译成类似Select TOP 1 * from Projects的东西。请注意0​​部分 - 这是限制返回行数的SQL Server运算符。这是SQL Server中查询优化的一部分。SQL Server没有任何运营商可以给你LAST 1 - 因为它需要运行查询,返回所有结果,拿走最后一个,然后转储剩下的结果 - 这不是很有效率,想象一下一对夫妇(双)百万条记录。

因此,您需要将任何所需的排序顺序应用于您的查询并限制您返回的行数。如果您需要查询中的最后一条记录 - 应用反向排序顺序。您确实需要排序,因为SQL Server does not guarantee order of records returned如果没有Order By应用于查询 - 这是由于数据存储在内部的方式。

当您使用EF编写LINQ查询时,我建议您留意您的查询生成的SQL - 有时您会看到它们出现的复杂程度,您可以轻松简化查询。有时候,延迟加载使得你可以引入N + 1的问题和一个关键字(字面意义上的)。我使用ExpressProfiler来观察生成的SQL,LinqPad也可以显示你的SQL查询和其他工具。

+0

有用的解释! –