このクエリでは:
_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());
}
_
動作させるにはこれに切り替える必要がありました
_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());
}
_
p.First()
を使用して最初のクエリをミラーリングすることさえできませんでした。
なぜこのような堅牢なORMシステムに基本的な制限があるのですか?
その制限は、最終的にはそのクエリを[〜#〜] sql [〜#〜]に変換する必要があり、SQLには_SELECT TOP
_(T-SQLで)があるが、 _SELECT BOTTOM
_ではありません(そのようなことはありません)。
しかし、それを回避する簡単な方法があります。降順し、First()
を実行します。これはあなたがしたことです。
編集:他のプロバイダーは_SELECT TOP 1
_の異なる実装を持つ可能性があり、Oracleではおそらく_WHERE ROWNUM = 1
_のようなものになります
編集:
もう1つの非効率的な代替手段これはお勧めしません!-.ToList()
の前にデータで.Last()
を呼び出すと、LINQ To Entities Expressionがすぐに実行されますそれはその時点までに構築されていて、その後.Last()が機能します。なぜなら、その時点で.Last()
はLINQ to Objects式のコンテキストで効果的に実行されるからです。代わりに。 (そして、あなたが指摘したように、それは何千ものレコードを取り戻し、使用されないオブジェクトを具体化するCPUの負荷を浪費する可能性があります)
繰り返しますが、この2番目の操作はお勧めしませんが、LINQ式が実行される場所とタイミングの違いを説明するのに役立ちます。
Last()
の代わりに、これを試してください:
model.OrderByDescending(o => o.Id).FirstOrDefault();
Last()
をLinqセレクターOrderByDescending(x => x.ID).Take(1).Single()
に置き換えます
あなたがLinqでそれを行うことを好めば、そのようなものはうまくいくでしょう:
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());
}
これは、LINQ to Entities(および一般的なデータベース)がすべてのLINQメソッドをサポートしていないためです(詳細についてはこちらを参照してください: http://msdn.Microsoft.com/en-us/library/bb738550.aspx )
ここで必要なのは、「最後の」レコードが「最初」になり、FirstOrDefaultを使用できるようにデータを順序付けることです。通常、databaseseには「最初」や「最後」などの概念はなく、最後に挿入されたレコードがテーブルの「最後」になるわけではないことに注意してください。
この方法で問題を解決できます
db.databaseTable.OrderByDescending(obj => obj.Id).FirstOrDefault();
さらに別の方法では、OrderByDescendingなしで最後の要素を取得し、すべてのエンティティをロードします。
dbSet
.Where(f => f.Id == dbSet.Max(f2 => f2.Id))
.FirstOrDefault();