はじめに
個人アプリの開発中に外部結合をして集計した値を取得する処理を書いたので備忘録として残しておきます。
LINQを用いた外部結合
以下に作成した処理を記載します。
Dim targetsGroupByCategoryId = _dbContext.ExpensesCategories _ .GroupJoin(_dbContext.Expenses.Where(Function(o) o.UseDate >= startDate And o.UseDate <= endDate), Function(ec) ec.CategoryId, Function(e) e.CategoryId, Function(ec, e) New With { ec, e }) _ .SelectMany( Function(o) o.e.DefaultIfEmpty(), Function(o, p) New With { o.ec.CategoryId, .Amounts = If(o.e.Select(Function(q) q.Amount).Any(), o.e.Select(Function(q) q.Amount).Sum(), 0) }) _ .GroupBy(Function(o) New With {o.CategoryId, o.Amounts}) _ .Select(Function(o) New With {o.Key}) _ .ToList()
※If(o.e.Select(Function(q) q.Amount).Any(), o.e.Select(Function(q) q.Amount).Sum(), 0)
部分は、結構大切でこれを入れなかった場合、結合後に値がNULLになるカラムがあった場合に処理が落ちてしまいます(NULLのSUMは処理できないため)。
※o.e.DefaultIfEmpty()
部分は結合元の行に結合先の行がない場合にそれぞれのカラムの初期値がセットされるようにする処理です。
おわりに
LINQのメソッド式は便利ではあるのですが、結合系はなかなかイメージがわきにくいので少し慣れが必要ですね...。 頑張って慣れていこうと思います!