2011-09-03 21 views
111

LINQ To EntitiesはLastメソッドを認識しません。本当に?このクエリで

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters 
     .OrderBy(p => p.ServerStatus.ServerDateTime) 
     .GroupBy(p => p.RawName) 
     .Select(p => p.Last()); 
} 

私はそれは私も最初のクエリをミラーリングするために、p.First()を使用することができませんでし

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters 
     .OrderByDescending(p => p.ServerStatus.ServerDateTime) 
     .GroupBy(p => p.RawName) 
     .Select(p => p.FirstOrDefault()); 
} 

を動作させるために、このに切り替えなければなりませんでした。

このような堅牢なORMシステムには、なぜ基本的な制限がありますか?制限は、最終的にはSQLにそのクエリを変換するために持っているとSQLがSELECT TOP(T-SQLで)ではなくSELECT BOTTOM(ノーようなもの)を持っているという事実に降りてくること

+0

IEnumrableオブジェクトを新しい変数に格納してから、variable.last()を返します。それが動作します。 –

答えて

174

周囲に簡単な方法がありますが、注文降順を入力してから、First()を実行してください。

EDIT: 他のプロバイダは、おそらくそれはおそらくより多くのようなWHERE ROWNUM = 1

EDITものになるだろうオラクルに、SELECT TOP 1の異なる実装があります:

別の少ない効率的な代替 - 私はしないでくださいこれをお勧めします! - .Last()の前にデータの.ToList()を呼び出すと、直ちにそのポイントまで構築されたLINQ To Entities Expressionが実行され、その時点で.Last()が有効に実行されるため、.Last()が機能します。その代わりにLINQ to Objects式のコンテキスト。 (そして、あなたが指摘したように、何千もの記録を取り戻し、決して使用されないオブジェクトを実現するCPUの無駄な負荷)

もう一度やり直すのはお勧めしませんが、 LINQ式が実行されたときに発生します。

+0

、LINQ To SQLはこのシナリオをどのように処理しますか? – bevacqua

+1

@ニコ:それは同様に投げます。 – jason

+0

@Neilはい私はToListを呼び出すことができると知っているが、データベースから何千ものレコードを取り出して、5つのレコードにフィルタリングするのではなく、 – bevacqua

12

あなたはLINQの中でそれを行うprefert場合はそのようなOrderByDescending(x => x.ID).Take(1).Single()

何かが作品になるLINQのセレクタによってLast()を交換してください:代わりにLast()

public static IEnumerable<IServerOnlineCharacter> GetUpdated() 
{ 
    var context = DataContext.GetDataContext(); 
    return context.ServerOnlineCharacters.OrderBy(p => p.ServerStatus.ServerDateTime).GroupBy(p => p.RawName).Select(p => p.OrderByDescending(x => x.Id).Take(1).Single()); 
} 
+0

これは私にとって完璧に機能しました。 –

+1

.FirstOrDefault()の代わりに.Take(1).Single()を使用する理由はありますか? –

+1

@TotZam有効な置換は、項目数が厳密に1でない場合にSingle()が例外をスローするため、その場合は.First()になります。 – MEMark

17

を、これを試してみてください:

model.OrderByDescending(o => o.Id).FirstOrDefault(); 
0

さらに別の方法は、OrderByDescendingなしで最後の要素を取得し、すべてのエンティティを読み込みます。

dbSet 
    .Where(f => f.Id == dbSet.Max(f2 => f2.Id)) 
    .FirstOrDefault(); 
関連する問題