カテゴリ: C# 更新日: 2026/02/20

C# Entity Framework CoreでLINQを使ったデータベース検索を完全解説!初心者向けガイド

C#のEF CoreでLINQを使ったデータ検索の書き方
C#のEF CoreでLINQを使ったデータ検索の書き方

先生と生徒の会話形式で理解しよう

生徒

「C#でデータベースからデータを検索する方法を教えてください。SQL文を書くのは難しそうで…」

先生

「それなら、Entity Framework CoreとLINQを使う方法がおすすめです。C#のコードだけでデータベース操作ができますよ。」

生徒

「LINQって何ですか?難しくないですか?」

先生

「LINQは、データを検索するための便利な機能です。日本語のような感覚でデータを取得できるので、初心者にも分かりやすいですよ。それでは、基本から見ていきましょう!」

1. Entity Framework CoreとLINQとは?

1. Entity Framework CoreとLINQとは?
1. Entity Framework CoreとLINQとは?

Entity Framework Core(EF Core)は、C#でデータベース操作を簡単にするための技術です。データベースというのは、たくさんの情報を整理して保管する場所のことです。例えば、図書館の本棚を思い浮かべてください。本棚には本が整理されて並んでいますね。データベースも同じように、商品情報や顧客情報などが整理されて保管されています。

LINQ(リンク)は、「Language Integrated Query」の略で、日本語では「統合言語クエリ」と呼ばれます。クエリとは「問い合わせ」という意味で、データベースに対して「このデータをください」とお願いすることです。LINQを使うと、C#のコードの中で自然な書き方でデータを検索できます。

従来はSQL(エスキューエル)という専用の言語でデータベースに問い合わせをしていましたが、LINQを使えばC#の文法だけでデータを取得できるため、初心者にも扱いやすくなっています。

2. EF CoreとLINQを使う準備

2. EF CoreとLINQを使う準備
2. EF CoreとLINQを使う準備

まず、EF Coreを使うための準備が必要です。Visual Studioなどの開発環境を使っている場合、NuGetパッケージマネージャーから必要なライブラリをインストールします。

必要なパッケージは以下の通りです:

  • Microsoft.EntityFrameworkCore - EF Coreの本体
  • Microsoft.EntityFrameworkCore.SqlServer - SQL Serverを使う場合
  • Microsoft.EntityFrameworkCore.Tools - 開発時に便利なツール

データベースには様々な種類がありますが、ここではSQL Serverを例に説明します。SQLiteやMySQLなど他のデータベースを使う場合は、対応するパッケージをインストールしてください。

DbContext(ディービーコンテキスト)というクラスを作成します。これは、データベースとの接続を管理する重要なクラスです。レストランで例えると、ウェイターのような役割を果たします。お客さん(プログラム)と厨房(データベース)の間でやり取りをしてくれるのです。

3. 基本的なデータ検索(全件取得)

3. 基本的なデータ検索(全件取得)
3. 基本的なデータ検索(全件取得)

まずは、データベースからすべてのデータを取得する方法を見てましょう。例として、商品情報を管理するProductテーブルからデータを取得します。


using (var context = new MyDbContext())
{
    // すべての商品を取得
    var products = context.Products.ToList();
    
    // 取得した商品を表示
    foreach (var product in products)
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
}

このコードでは、context.ProductsでProductsテーブルにアクセスし、ToList()ですべてのデータをリスト形式で取得しています。ToList()は、データベースに実際に問い合わせを行うメソッドです。これを呼び出すまでは、データベースへの問い合わせは実行されません。

foreach文は、取得したデータを一つずつ取り出して処理するための構文です。リストの中身を順番に見ていくイメージですね。

4. 条件を指定したデータ検索(Where句)

4. 条件を指定したデータ検索(Where句)
4. 条件を指定したデータ検索(Where句)

特定の条件に合うデータだけを取得したい場合は、Whereメソッドを使います。これは、SQL文のWHERE句と同じ役割を果たします。


using (var context = new MyDbContext())
{
    // 価格が1000円以上の商品を取得
    var expensiveProducts = context.Products
        .Where(p => p.Price >= 1000)
        .ToList();
    
    foreach (var product in expensiveProducts)
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
}

Where(p => p.Price >= 1000)という部分が条件指定です。p => p.Price >= 1000ラムダ式と呼ばれる書き方で、「pという変数に対して、そのPriceが1000以上のもの」という意味になります。矢印(=>)の左側が変数、右側が条件です。

これは、図書館で「値段が1000円以上の本を探してください」とお願いするのと同じです。すべての本を調べて、条件に合う本だけを返してくれます。

5. 複数の条件を組み合わせたデータ検索

5. 複数の条件を組み合わせたデータ検索
5. 複数の条件を組み合わせたデータ検索

複数の条件を組み合わせてデータを検索することもできます。&&(かつ)や||(または)を使って条件を組み合わせます。


using (var context = new MyDbContext())
{
    // 価格が500円以上1500円以下で、在庫がある商品を取得
    var availableProducts = context.Products
        .Where(p => p.Price >= 500 && p.Price <= 1500 && p.Stock > 0)
        .ToList();
    
    Console.WriteLine($"該当する商品数: {availableProducts.Count}件");
    
    foreach (var product in availableProducts)
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円, 在庫: {product.Stock}個");
    }
}

&&は「かつ(AND)」を意味し、すべての条件を満たす必要があります。||は「または(OR)」を意味し、いずれかの条件を満たせば該当します。

この例では、「価格が500円以上」かつ「価格が1500円以下」かつ「在庫が0より多い」という3つの条件すべてを満たす商品を検索しています。買い物をするとき、「予算内で、在庫がある商品」を探すのと同じ感覚です。

6. データの並び替え(OrderBy、OrderByDescending)

6. データの並び替え(OrderBy、OrderByDescending)
6. データの並び替え(OrderBy、OrderByDescending)

取得したデータを特定の順番に並び替えるには、OrderBy(昇順)またはOrderByDescending(降順)を使います。昇順とは小さい順、降順とは大きい順のことです。


using (var context = new MyDbContext())
{
    // 商品を価格の安い順に並び替え
    var sortedProducts = context.Products
        .OrderBy(p => p.Price)
        .ToList();
    
    Console.WriteLine("=== 価格の安い順 ===");
    foreach (var product in sortedProducts.Take(5))
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
    
    // 商品を価格の高い順に並び替え
    var descendingProducts = context.Products
        .OrderByDescending(p => p.Price)
        .ToList();
    
    Console.WriteLine("\n=== 価格の高い順 ===");
    foreach (var product in descendingProducts.Take(5))
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
}

OrderBy(p => p.Price)で価格の安い順(昇順)に、OrderByDescending(p => p.Price)で価格の高い順(降順)に並び替えられます。Take(5)は、先頭から5件だけを取得するメソッドです。

本を並べるとき、背の低い順や高い順に整理するのと同じイメージです。検索結果を見やすく整理するために、並び替えはとても便利な機能です。

7. 特定の1件だけを取得する方法

7. 特定の1件だけを取得する方法
7. 特定の1件だけを取得する方法

条件に合う最初の1件だけを取得したい場合は、FirstOrDefaultSingleOrDefaultを使います。両者の違いを理解することが大切です。

FirstOrDefaultは、条件に合う最初のデータを返します。該当するデータがない場合はnullを返します。複数のデータが該当しても、最初の1件だけを返します。

SingleOrDefaultは、条件に合うデータが1件だけの場合にそれを返します。該当するデータがない場合はnullを返し、2件以上ある場合はエラーになります。「絶対に1件しかないはず」というデータを取得するときに使います。


using (var context = new MyDbContext())
{
    // IDが1の商品を取得(IDは通常1件のみなのでSingleOrDefaultを使用)
    var product = context.Products
        .SingleOrDefault(p => p.Id == 1);
    
    if (product != null)
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
    else
    {
        Console.WriteLine("該当する商品が見つかりませんでした。");
    }
    
    // 最も安い商品を1件取得
    var cheapestProduct = context.Products
        .OrderBy(p => p.Price)
        .FirstOrDefault();
    
    if (cheapestProduct != null)
    {
        Console.WriteLine($"最安値商品: {cheapestProduct.Name}, 価格: {cheapestProduct.Price}円");
    }
}

このコードでは、まずIDで商品を検索し、次に最も安い商品を取得しています。if文でnullチェックをすることで、データが見つからなかった場合のエラーを防いでいます。

8. 部分一致検索(文字列検索)

8. 部分一致検索(文字列検索)
8. 部分一致検索(文字列検索)

商品名などの文字列で部分一致検索をする場合は、ContainsStartsWithEndsWithメソッドを使います。これは、Googleで検索するときのように、一部の文字だけで検索できる機能です。

Containsは「含む」、StartsWithは「で始まる」、EndsWithは「で終わる」という意味です。


using (var context = new MyDbContext())
{
    string searchWord = "ノート";
    
    // 商品名に「ノート」を含む商品を検索
    var matchedProducts = context.Products
        .Where(p => p.Name.Contains(searchWord))
        .ToList();
    
    Console.WriteLine($"「{searchWord}」を含む商品:");
    foreach (var product in matchedProducts)
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
    
    // 「新」で始まる商品を検索
    var newProducts = context.Products
        .Where(p => p.Name.StartsWith("新"))
        .ToList();
    
    Console.WriteLine("\n「新」で始まる商品:");
    foreach (var product in newProducts)
    {
        Console.WriteLine($"商品名: {product.Name}");
    }
}

この検索方法は、ECサイトの商品検索機能などでよく使われます。ユーザーが入力したキーワードをsearchWord変数に入れて、Containsで部分一致検索をすることで、柔軟な検索機能を実装できます。

9. データの件数を取得する(Count)

9. データの件数を取得する(Count)
9. データの件数を取得する(Count)

条件に合うデータが何件あるかを知りたい場合は、Countメソッドを使います。すべてのデータを取得せずに件数だけを取得できるため、効率的です。

また、データが存在するかどうかだけを確認したい場合は、Anyメソッドが便利です。Anyは、条件に合うデータが1件でもあればtrue、なければfalseを返します。


using (var context = new MyDbContext())
{
    // すべての商品数を取得
    int totalCount = context.Products.Count();
    Console.WriteLine($"商品の総数: {totalCount}件");
    
    // 在庫がある商品の件数を取得
    int inStockCount = context.Products.Count(p => p.Stock > 0);
    Console.WriteLine($"在庫あり商品: {inStockCount}件");
    
    // 1000円以上の商品が存在するか確認
    bool hasExpensiveProduct = context.Products.Any(p => p.Price >= 1000);
    
    if (hasExpensiveProduct)
    {
        Console.WriteLine("1000円以上の商品が存在します。");
    }
    else
    {
        Console.WriteLine("1000円以上の商品はありません。");
    }
}

Count()メソッドは引数なしで使うとすべての件数を、引数に条件を指定すると条件に合う件数を返します。大量のデータを扱うシステムでは、Countを使うことでメモリの節約になります。

10. LINQのメソッドチェーンで複雑な検索

10. LINQのメソッドチェーンで複雑な検索
10. LINQのメソッドチェーンで複雑な検索

LINQの強力な点は、複数のメソッドを繋げて(メソッドチェーン)、複雑な検索を簡潔に書けることです。条件指定、並び替え、件数制限などを組み合わせることができます。


using (var context = new MyDbContext())
{
    // 在庫があり、価格が500円以上の商品を、価格の安い順に並べて、上位10件を取得
    var topProducts = context.Products
        .Where(p => p.Stock > 0 && p.Price >= 500)
        .OrderBy(p => p.Price)
        .Take(10)
        .ToList();
    
    Console.WriteLine("おすすめ商品トップ10:");
    int rank = 1;
    foreach (var product in topProducts)
    {
        Console.WriteLine($"{rank}位: {product.Name} - {product.Price}円 (在庫: {product.Stock}個)");
        rank++;
    }
    
    // 商品名に「ペン」を含む商品を価格の高い順に並べて、3件目から5件を取得
    var penProducts = context.Products
        .Where(p => p.Name.Contains("ペン"))
        .OrderByDescending(p => p.Price)
        .Skip(2)
        .Take(5)
        .ToList();
    
    Console.WriteLine("\n「ペン」を含む商品(3位~7位):");
    foreach (var product in penProducts)
    {
        Console.WriteLine($"商品名: {product.Name}, 価格: {product.Price}円");
    }
}

Skipメソッドは、指定した件数だけデータを読み飛ばします。Skip(2).Take(5)とすることで、「最初の2件を飛ばして、次の5件を取得する」という処理ができます。これは、ページング処理(ページ分割)を実装するときに便利です。

メソッドチェーンは、上から順番に処理されます。まずWhereで条件に合うデータを絞り込み、次にOrderByで並び替え、最後にTakeで件数を制限する、という流れです。水道の蛇口に複数のフィルターを付けるようなイメージで、段階的にデータを絞り込んでいきます。

11. よくあるエラーと対処法

11. よくあるエラーと対処法
11. よくあるエラーと対処法

LINQを使ったデータベース検索で初心者がよく遭遇するエラーと、その対処法を紹介します。

エラー1: NullReferenceException

データが見つからないときにnullを参照してしまうエラーです。FirstOrDefaultSingleOrDefaultを使った後は、必ずnullチェックをしましょう。


var product = context.Products.FirstOrDefault(p => p.Id == 999);
// productがnullの可能性があるので、チェックが必要
if (product != null)
{
    Console.WriteLine(product.Name);
}
エラー2: InvalidOperationException(Sequenceに複数の要素が含まれています)

SingleSingleOrDefaultを使ったとき、条件に合うデータが2件以上あるとこのエラーが発生します。データが1件だけと確信できない場合は、FirstOrDefaultを使いましょう。

エラー3: ToListを忘れる

LINQのクエリは遅延実行という特性があり、ToList()Count()などを呼び出すまでデータベースへの問い合わせは実行されません。結果を確実に取得するには、ToList()を忘れずに付けましょう。

カテゴリの一覧へ
新着記事
New1
C#
C#のstaticクラスとstaticメソッドの基本と使い方をやさしく解説!
New2
COBOL
COBOLのサブルーチン活用!初心者でもわかる再利用できる部品の作り方と使い方
New3
C#
C# Entity Framework CoreでLINQを使ったデータベース検索を完全解説!初心者向けガイド
New4
COBOL
COBOLのCALL BY REFERENCEとCALL BY CONTENTの違いを完全解説!初心者向けにやさしく解説
人気記事
No.1
Java&Spring記事人気No1
C#
C#のpartialクラスとは?初心者でも理解できるクラス分割の基本
No.2
Java&Spring記事人気No2
C#
C#のLINQでOrderByを使った並び替えを完全ガイド!初心者でもわかるソート方法
No.3
Java&Spring記事人気No3
C#
C#のデータベース接続文字列の設定方法を完全ガイド!ADO.NETとEntity Framework初心者向け
No.4
Java&Spring記事人気No4
C#
C#のラムダ式の書き方と構文を初心者向けに完全解説
No.5
Java&Spring記事人気No5
COBOL
COBOLのCOPY句の使い方を完全ガイド!初心者でもわかる共通部品の再利用方法
No.6
Java&Spring記事人気No6
C#
C#のトランザクション処理を完全ガイド!初心者でもわかるCommit・Rollbackの使い方
No.7
Java&Spring記事人気No7
C#
C#でデータを取得する基本!ExecuteReader・ExecuteScalarの違いを初心者向けに解説
No.8
Java&Spring記事人気No8
C#
C#の文字列を数値に変換する方法(int.Parse・TryParse)をわかりやすく解説!