2017-04-13 83 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

有用的解釋! –