記事詳細
- 投稿日
- 2025年11月24日11時54分
-
タイトル
-
userIdのフィルターをかけるコード
- 内容
-
コードでは、 の取得時に ログイン中ユーザーの
UserIdでフィルタをかけたいということですね。
さらに、月別集計やページングにも対応できる形にリファクタリングします。paymentsNumMonth1. 単純に フィルタを追加する場合
UserIdvar userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(userId)) { // 未ログイン時の処理 return RedirectToAction("Login", "Account"); } var paymentsNumMonth = _context.Payment .Include(p => p.SubjectName) .Where(p => p.UserId == userId) // ★ ユーザーIDでフィルタ .Where(p => p.Posted >= firstDayOfMonth && p.Posted <= lastDayOfMonth) .ToList();2. 月別集計・ページング対応にリファクタリング
- ポイント
IQueryableを使ってフィルタを段階的に適用(集計やページングに対応しやすい)- ページングは と を使用
SkipTake - 集計は を使って月ごとにまとめられる
GroupBy
using Microsoft.EntityFrameworkCore; using System.Security.Claims; public IActionResult Payments(int year, int month, int page = 1, int pageSize = 20) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (string.IsNullOrEmpty(userId)) { return RedirectToAction("Login", "Account"); } // 月初と月末を計算 var firstDayOfMonth = new DateTime(year, month, 1); var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1); // ベースクエリ(IQueryable) var query = _context.Payment .Include(p => p.SubjectName) .Where(p => p.UserId == userId) // ユーザーIDでフィルタ .Where(p => p.Posted >= firstDayOfMonth && p.Posted <= lastDayOfMonth) .OrderBy(p => p.Posted) // 並び順 // IQueryableなのでまだDBにアクセスしない ; // ページング var totalCount = query.Count(); var payments = query .Skip((page - 1) * pageSize) .Take(pageSize) .ToList(); // 月別集計例(合計金額) var monthlySummary = _context.Payment .Where(p => p.UserId == userId) .GroupBy(p => new { p.Posted.Year, p.Posted.Month }) .Select(g => new { Year = g.Key.Year, Month = g.Key.Month, TotalAmount = g.Sum(x => x.Amount) }) .OrderByDescending(x => x.Year) .ThenByDescending(x => x.Month) .ToList(); // ViewModelにまとめて返す var model = new PaymentsViewModel { Payments = payments, TotalCount = totalCount, Page = page, PageSize = pageSize, MonthlySummary = monthlySummary }; return View(model); } // ViewModel例 public class PaymentsViewModel { public List<Payment> Payments { get; set; } public int TotalCount { get; set; } public int Page { get; set; } public int PageSize { get; set; } public List<object> MonthlySummary { get; set; } }このリファクタリングのメリット
- UserId フィルタが共通化され、どの集計やページングにも適用される
- IQueryable を使うことで、必要な条件を後から追加可能
- ページング ( / ) と集計 () を分離して管理できる
SkipTakeGroupBy - 大量データでも効率的に動作(SQL に変換されて DB 側で処理)
もし希望があれば、このコードを 月別集計とページングを同時に行う API 形式 にもできます。
そうすれば SPA やフロントエンドからの非同期呼び出しにも対応できます。この後、私が提案するのは 「共通フィルタを適用する拡張メソッド化」 です。
そうすると、どのコントローラでも のように書けます。
これを作りますか?query.FilterByUser(userId)Powered by Froala Editor
- ポイント
-
添付画像
-
画像はありません
- Genreのカテゴリ-名
- Controllers