IQueryableクエリ文のOrderByDescending()拡張メソッド使用上の注意点

4842 ワード

目的:構造物の下のすべてのゲートウェイの最新診断結果を照会する.
 
1.正しいクエリ(診断時の逆)
var query = queryDiag.GroupBy(g => new {g.dtuId, g.dtuNo, g.dtuDesp})
                    .Select(s =>
                        s.GroupBy(r => r.diagTime)
                            .Select(e => new
                            {
                                s.Key.dtuId,
                                s.Key.dtuNo,
                                s.Key.dtuDesp,
                                diagTime = e.Key,
                                cpuRatio = e.Where(w => w.diagName == iDAUDiagEntity.CpuRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                memoryRatio = e.Where(w => w.diagName == iDAUDiagEntity.MemoryRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                flashRatio = e.Where(w => w.diagName == iDAUDiagEntity.FlashRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                sdRatio = e.Where(w => w.diagName == iDAUDiagEntity.SdRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                gatewayWorkDuration = e.Where(w => w.diagName == iDAUDiagEntity.GatewayWorkDuration)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                serverWorkDuration = e.Where(w => w.diagName == iDAUDiagEntity.ServerWorkDuration)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                nodesCount = e.Select(l => l.nodesCount).FirstOrDefault()
                            }).OrderByDescending(o => o.diagTime).FirstOrDefault());

クエリの結果:
構造下の各ゲートウェイの最新診断結果.
 
2.エラークエリ(ソートの目的が達成されていない)
次のコードに示すように、クエリ文の「.OrderByDescending()」を下の位置に調整します.
var query = queryDiag.GroupBy(g => new {g.dtuId, g.dtuNo, g.dtuDesp})
                    .Select(s =>
                        s.OrderByDescending(o => o.diagTime).GroupBy(r => r.diagTime)
                            .Select(e => new
                            {
                                s.Key.dtuId,
                                s.Key.dtuNo,
                                s.Key.dtuDesp,
                                diagTime = e.Key,
                                cpuRatio = e.Where(w => w.diagName == iDAUDiagEntity.CpuRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                memoryRatio = e.Where(w => w.diagName == iDAUDiagEntity.MemoryRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                flashRatio = e.Where(w => w.diagName == iDAUDiagEntity.FlashRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                sdRatio = e.Where(w => w.diagName == iDAUDiagEntity.SdRatio)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                gatewayWorkDuration = e.Where(w => w.diagName == iDAUDiagEntity.GatewayWorkDuration)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                serverWorkDuration = e.Where(w => w.diagName == iDAUDiagEntity.ServerWorkDuration)
                                    .Select(l => l.diagResult).FirstOrDefault(),
                                nodesCount = e.Select(l => l.nodesCount).FirstOrDefault()
                            }).FirstOrDefault());

クエリの結果:
所期の結果に達していない場合、最も遅い診断記録であるか、履歴診断のいずれかの記録である可能性がある.
 
【まとめ】
IQueryableクエリ文でOrderByDescending()拡張メソッドを使用する場合は、次の点に注意してください.
結果セットを時系列に並べ替える必要がある場合は、「OrderByDescending()」拡張メソッドを後にする必要がある.
前に置くと、LINQ文変換後のSQL文には「order by」のソート条件がないため、逆の効果は得られない.