関連テーブルのレコードを複数持つレコードを取得するとき、関連テーブルの要素のソートされた状態で取得したい。
test.cs
var items = ctx.Item
.Include(x => x.Tags)
.Where(x => x.Tags.Any())
.OrderByDescending(x => x.Id);
具体的に言うと上記のTagもソートした状態で取得したい。
しかし、Tagsのどれでソートするという情報をOrderByで書く方法がわからなかった。
test.cs
var items = ctx.Item
.Include(x => x.Tags)
.Where(x => x.Tags.Any())
.OrderByDescending(x => x.Id)
.ThenBy("Tags.Id"); // Tag.Idでソートをしたいがこういう書き方はできない
1時間くらい調べてみたがどうもできないっぽい?
できないのであればしょうがないので取得後にやるしかない。
しかし、表示部分でソート処理を入れると忘れたとき悲惨なのでこのメソッドチェーンに書いておきたい。
test.cs
var items = ctx.Item
.Include(x => x.Tags)
.Where(x => x.Tags.Any())
.OrderByDescending(x => x.Id)
.AsEnumerable().Select(x =>
{
x.Tags = x.Tags.OrderBy(tag => tag.Id).ToArray();
return x;
}).ToArray(); // 無理矢理。。
ちなみに.AsEnumerable()は終端操作ではないので遅延実行はできる。
上記で言うとToArray()で発火。
ただし、AsEnumerable以前のチェーンがクエリ発行の対象になるため、それ以降にWhereとか書いても実行SQLには反映されず、SQL実行後に生成されたIEnumerableへの操作となるため注意しなければならない。
バッドノウハウっぽい記事になってしまった。
もっとスマートなやり方がありそうだが、時間切れ。