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

C#のDataReaderとDataAdapterの違いを徹底解説!ADO.NETのデータベース操作を完全マスター

C#のDataReaderとDataAdapterの違いを理解しよう
C#のDataReaderとDataAdapterの違いを理解しよう

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

生徒

「C#でデータベースからデータを取得する方法って、いくつかあるんですか?」

先生

「はい、ADO.NETというデータベース操作の仕組みでは、主にDataReaderとDataAdapterという2つの方法があります。」

生徒

「2つもあるんですね。どう違うんですか?使い分けとかありますか?」

先生

「それぞれ特徴があって、状況によって使い分けるんです。それでは、詳しく見ていきましょう!」

1. DataReaderとDataAdapterとは?基本を理解しよう

1. DataReaderとDataAdapterとは?基本を理解しよう
1. DataReaderとDataAdapterとは?基本を理解しよう

C#でデータベースを操作する際に使うADO.NET(エーディーオー・ドット・ネット)には、データを取得する方法がいくつかあります。その中でも代表的なのがDataReader(データリーダー)とDataAdapter(データアダプター)です。

これらは両方ともデータベースからデータを取得するために使いますが、動作の仕組みや使い方が大きく異なります。ADO.NETとは、マイクロソフトが提供するデータベースにアクセスするための技術で、SQL ServerやMySQL、Oracleなど様々なデータベースに接続できます。

まず、それぞれの特徴を簡単に説明すると、DataReaderは「高速で軽量」、DataAdapterは「柔軟で多機能」という違いがあります。この違いを理解することで、適切な方法を選択できるようになります。

2. DataReaderの特徴と使い方

2. DataReaderの特徴と使い方
2. DataReaderの特徴と使い方

DataReaderは、データベースから取得したデータを順番に一方向で読み取るための仕組みです。例えるなら、カセットテープのように「早送りはできるけど、巻き戻しはできない」というイメージです。

DataReaderの主な特徴は以下の通りです:

  • 高速:データを読み取るスピードが速い
  • 軽量:メモリの使用量が少ない
  • 接続型:データベースとの接続を保ったまま操作する
  • 読み取り専用:データの参照だけができる(更新はできない)
  • 前方向のみ:データを順番に読み進むことしかできない

DataReaderを使う場合は、データベースに接続したまま処理を行います。これを「接続型アクセス」と呼びます。接続したままなので、処理が終わったらすぐに接続を閉じる必要があります。

それでは、実際のコードで見てみましょう。以下は、SQL Serverのデータベースから顧客情報を取得する例です:


using System;
using System.Data.SqlClient;

class Program
{
    static void Main()
    {
        // データベースへの接続文字列
        string connectionString = "Server=localhost;Database=SampleDB;Trusted_Connection=True;";
        
        // SqlConnectionオブジェクトを作成
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            // データベースに接続
            connection.Open();
            
            // SQL文を作成
            string sql = "SELECT CustomerID, CustomerName FROM Customers";
            
            // SqlCommandオブジェクトを作成
            SqlCommand command = new SqlCommand(sql, connection);
            
            // DataReaderを使ってデータを取得
            using (SqlDataReader reader = command.ExecuteReader())
            {
                // データが存在する限り繰り返す
                while (reader.Read())
                {
                    // データを取得して表示
                    int id = reader.GetInt32(0);  // 1列目を取得
                    string name = reader.GetString(1);  // 2列目を取得
                    Console.WriteLine($"ID: {id}, 名前: {name}");
                }
            }
            // usingブロックを抜けると自動的に接続が閉じられる
        }
    }
}

このコードでは、ExecuteReader()メソッドを呼び出してDataReaderを取得し、Read()メソッドで1行ずつデータを読み取っています。Read()メソッドは、次のデータがある場合はtrueを返し、データがなくなるとfalseを返します。

DataReaderは、大量のデータを高速に読み取りたい場合や、単純にデータを表示するだけの場合に最適です。

3. DataAdapterの特徴と使い方

3. DataAdapterの特徴と使い方
3. DataAdapterの特徴と使い方

DataAdapterは、データベースとDataSetやDataTableというデータの入れ物の間を橋渡しする役割を持っています。例えるなら、「トラックでデータを運んで、倉庫に保管する」というイメージです。

DataAdapterの主な特徴は以下の通りです:

  • 非接続型:データを取得したらデータベースとの接続を切断できる
  • DataSetと連携:メモリ上にデータを保持できる
  • 更新が可能:データの追加、更新、削除ができる
  • 自由なアクセス:データを何度でも読み返せる
  • バッチ更新:複数の変更をまとめてデータベースに反映できる

DataAdapterを使う場合、データは一度メモリ上のDataSetやDataTableに読み込まれます。これにより、データベース接続を切断した後も自由にデータを操作できます。これを「非接続型アクセス」と呼びます。

それでは、DataAdapterを使った実際のコードを見てみましょう:


using System;
using System.Data;
using System.Data.SqlClient;

class Program
{
    static void Main()
    {
        // データベースへの接続文字列
        string connectionString = "Server=localhost;Database=SampleDB;Trusted_Connection=True;";
        
        // SqlConnectionオブジェクトを作成
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            // SQL文を作成
            string sql = "SELECT ProductID, ProductName, Price FROM Products";
            
            // SqlDataAdapterオブジェクトを作成
            SqlDataAdapter adapter = new SqlDataAdapter(sql, connection);
            
            // DataTableオブジェクトを作成(データの入れ物)
            DataTable dataTable = new DataTable();
            
            // DataAdapterを使ってデータをDataTableに格納
            adapter.Fill(dataTable);
            
            // この時点でデータベース接続は自動的に閉じられている
            
            // DataTableからデータを取り出して表示
            foreach (DataRow row in dataTable.Rows)
            {
                int id = Convert.ToInt32(row["ProductID"]);
                string name = row["ProductName"].ToString();
                decimal price = Convert.ToDecimal(row["Price"]);
                Console.WriteLine($"商品ID: {id}, 商品名: {name}, 価格: {price}円");
            }
            
            // データを自由に何度でも読み返せる
            Console.WriteLine($"\n取得した商品数: {dataTable.Rows.Count}件");
        }
    }
}

このコードでは、Fill()メソッドを呼び出すだけで、データベースへの接続、データの取得、接続の切断が自動的に行われます。取得したデータはDataTableに保存されるので、何度でも自由にアクセスできます。

DataAdapterは、データを編集したり、複数のテーブルを扱ったり、オフラインでデータを操作したい場合に便利です。

4. DataReaderとDataAdapterの違いを比較表で理解する

4. DataReaderとDataAdapterの違いを比較表で理解する
4. DataReaderとDataAdapterの違いを比較表で理解する

DataReaderとDataAdapterの違いを、わかりやすく表にまとめました:

比較項目 DataReader DataAdapter
接続方式 接続型(Connected) 非接続型(Disconnected)
データの読み取り 前方向のみ(一方通行) 自由にアクセス可能
速度 高速 やや遅い
メモリ使用量 少ない 多い
データの更新 不可(読み取り専用) 可能
データの保持 保持しない DataSet/DataTableに保持
使用するクラス SqlDataReaderなど SqlDataAdapterなど
適した用途 大量データの読み取り、表示のみ データ編集、複雑な操作

この表を見ると、DataReaderは「スピード重視でシンプル」、DataAdapterは「柔軟性重視で多機能」という特徴があることがわかります。

5. 接続型と非接続型の違いを詳しく知ろう

5. 接続型と非接続型の違いを詳しく知ろう
5. 接続型と非接続型の違いを詳しく知ろう

DataReaderとDataAdapterの最も大きな違いは、接続型非接続型かという点です。これを理解することで、どちらを使うべきかが判断しやすくなります。

接続型(Connected)とは

接続型は、データベースに接続したままデータを操作する方式です。DataReaderがこの方式を採用しています。蛇口をひねって水を出し続けているような状態で、使い終わったらすぐに蛇口を閉める必要があります。

接続型のメリットは、データベースから直接データを読み取るため高速で、メモリの使用量も少ないことです。デメリットは、データベースとの接続を占有してしまうため、長時間の処理には向きません。

非接続型(Disconnected)とは

非接続型は、必要なデータを一度取得したら、データベースとの接続を切断して、メモリ上でデータを操作する方式です。DataAdapterがこの方式を採用しています。お店で商品を買って家に持ち帰り、家でゆっくり使うようなイメージです。

非接続型のメリットは、データベースの接続を長時間占有しないため、複数のユーザーが同時にアクセスするアプリケーションに適していることです。また、オフライン(ネットワークに繋がっていない状態)でもデータを操作できます。デメリットは、すべてのデータをメモリに読み込むため、大量のデータを扱う場合はメモリを多く消費することです。

6. DataReaderを使うべき場面

6. DataReaderを使うべき場面
6. DataReaderを使うべき場面

DataReaderは、以下のような場面で使うと効果的です:

  • 大量のデータを読み取る場合:数万件、数十万件のレコードを処理する際、メモリ使用量を抑えられます
  • データを一度だけ読めばよい場合:レポート出力やログ表示など、読み取るだけの処理
  • パフォーマンスが重要な場合:高速な処理が求められるシステム
  • リアルタイムでデータを表示する場合:検索結果をすぐに画面に表示したい時

例えば、ECサイトで商品の一覧を表示する場合、ユーザーはただ商品を見るだけなので、DataReaderを使うのが適しています。


using System;
using System.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = "Server=localhost;Database=ShopDB;Trusted_Connection=True;";
        
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            
            // 在庫がある商品のみを取得
            string sql = "SELECT ProductName, Price, Stock FROM Products WHERE Stock > 0";
            SqlCommand command = new SqlCommand(sql, connection);
            
            using (SqlDataReader reader = command.ExecuteReader())
            {
                Console.WriteLine("【在庫あり商品一覧】");
                Console.WriteLine("------------------------");
                
                while (reader.Read())
                {
                    string productName = reader.GetString(0);
                    decimal price = reader.GetDecimal(1);
                    int stock = reader.GetInt32(2);
                    
                    Console.WriteLine($"商品名: {productName}");
                    Console.WriteLine($"価格: {price:C}");
                    Console.WriteLine($"在庫数: {stock}個");
                    Console.WriteLine("------------------------");
                }
            }
        }
    }
}

このコードは在庫のある商品を表示するだけなので、DataReaderが最適です。データを読み取ったらすぐに表示し、処理が終わったら接続を閉じます。

7. DataAdapterを使うべき場面

7. DataAdapterを使うべき場面
7. DataAdapterを使うべき場面

DataAdapterは、以下のような場面で使うと効果的です:

  • データを更新する必要がある場合:ユーザーがデータを編集して保存する機能
  • 複数のテーブルを扱う場合:複雑なデータ構造を操作する時
  • オフラインでデータを操作したい場合:ネットワーク接続がない環境でも作業できる
  • データを何度も参照する場合:同じデータに繰り返しアクセスする処理
  • DataGridViewなどのコントロールにバインドする場合:Windowsフォームアプリケーションで表を表示する時

例えば、従業員管理システムで従業員情報を編集して保存する場合、DataAdapterが適しています:


using System;
using System.Data;
using System.Data.SqlClient;

class Program
{
    static void Main()
    {
        string connectionString = "Server=localhost;Database=CompanyDB;Trusted_Connection=True;";
        
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            // 従業員データを取得
            string selectSql = "SELECT EmployeeID, EmployeeName, Salary FROM Employees";
            SqlDataAdapter adapter = new SqlDataAdapter(selectSql, connection);
            
            // 更新用のコマンドを自動生成
            SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
            
            DataTable employeeTable = new DataTable();
            adapter.Fill(employeeTable);
            
            // データを表示
            Console.WriteLine("【従業員一覧】");
            foreach (DataRow row in employeeTable.Rows)
            {
                Console.WriteLine($"ID: {row["EmployeeID"]}, 名前: {row["EmployeeName"]}, 給与: {row["Salary"]}円");
            }
            
            // データを更新(例:ID=1の従業員の給与を変更)
            DataRow[] targetRows = employeeTable.Select("EmployeeID = 1");
            if (targetRows.Length > 0)
            {
                targetRows[0]["Salary"] = 350000;
                Console.WriteLine("\n給与を更新しました。");
            }
            
            // 変更をデータベースに反映
            adapter.Update(employeeTable);
            Console.WriteLine("データベースに保存しました。");
        }
    }
}

このコードでは、DataTableにデータを読み込んでから編集し、最後にUpdate()メソッドでデータベースに変更を保存しています。このような更新処理にはDataAdapterが必須です。

8. パフォーマンスとメモリ使用量の違い

8. パフォーマンスとメモリ使用量の違い
8. パフォーマンスとメモリ使用量の違い

DataReaderとDataAdapterでは、パフォーマンス(処理速度)とメモリ使用量に大きな違いがあります。これを理解すると、システム設計の際に適切な選択ができます。

DataReaderのパフォーマンス

DataReaderは、データベースから直接データを読み取るため、非常に高速です。1行ずつ順番に処理するため、メモリには現在読み取っている1行分のデータしか保持しません。100万件のデータを処理する場合でも、メモリ使用量はほぼ一定です。

ただし、データベースとの接続を保ったまま処理するため、処理に時間がかかると他のユーザーに影響を与える可能性があります。

DataAdapterのパフォーマンス

DataAdapterは、すべてのデータをメモリ上のDataTableに読み込むため、データ量が多いとメモリを大量に消費します。100万件のデータを読み込むと、メモリが不足してプログラムが停止する可能性もあります。

しかし、一度データを読み込んでしまえば、データベース接続を切断できるため、複数のユーザーが同時にアクセスするシステムでは有利です。また、メモリ上でデータを操作できるため、複雑な処理や繰り返し参照する処理では高速です。

メモリとは?

メモリとは、パソコンがプログラムを実行する際に一時的にデータを保存する場所です。メモリの容量が大きいほど、多くのデータを同時に扱えます。メモリが不足すると、パソコンの動作が遅くなったり、プログラムがエラーになったりします。

9. 実践的な使い分けの判断基準

9. 実践的な使い分けの判断基準
9. 実践的な使い分けの判断基準

実際のプロジェクトで、DataReaderとDataAdapterのどちらを使うべきか迷った時の判断基準を紹介します:

DataReaderを選ぶ基準

  • 取得するデータ量が非常に多い(数万件以上)
  • データを表示するだけで、編集や更新は不要
  • 処理速度を最優先したい
  • メモリの使用量を抑えたい
  • レポート作成やログ出力など、一方向の処理

DataAdapterを選ぶ基準

  • データの追加、更新、削除が必要
  • 同じデータを何度も参照する
  • 複数のテーブルのデータを組み合わせて処理する
  • DataGridViewなどのUIコントロールと連携する
  • オフラインでデータを操作したい
  • バッチ処理でまとめて更新したい
注意点

どちらの方法を選んでも、必ずusingステートメントやClose()メソッドを使って、リソースを適切に解放することが重要です。接続やリーダーを開きっぱなしにすると、データベースに負荷がかかり、他のユーザーがアクセスできなくなる可能性があります。

10. Entity Frameworkとの関係

10. Entity Frameworkとの関係
10. Entity Frameworkとの関係

最後に、Entity Framework(エンティティ フレームワーク)との関係について触れておきます。Entity Frameworkは、ADO.NETをさらに使いやすくした、より高度なデータベース操作の仕組みです。

Entity Frameworkを使うと、DataReaderやDataAdapterを直接使わなくても、簡単にデータベース操作ができます。しかし、内部的にはADO.NETの仕組みを使っているため、DataReaderとDataAdapterの違いを理解しておくことは重要です。

特に、Entity Frameworkでも「即座にデータを取得する」か「遅延読み込みをする」かという選択肢があり、これはDataReaderとDataAdapterの違いに通じるものがあります。基礎をしっかり理解することで、より高度な技術も使いこなせるようになります。

ポイント

ADO.NETのDataReaderとDataAdapterは、それぞれ異なる目的と特徴を持っています。DataReaderは高速で軽量な読み取り専用の接続型アクセス、DataAdapterは柔軟で多機能な非接続型アクセスです。用途に応じて適切に使い分けることで、効率的なデータベースアプリケーションを開発できます。

カテゴリの一覧へ
新着記事
New1
C#
C#の拡張メソッドとは?既存クラスに機能を追加する便利技
New2
COBOL
COBOLのデータ型変換&MOVE CORRESPONDING完全解説!初心者でもできる編集と移送
New3
C#
C#のDataReaderとDataAdapterの違いを徹底解説!ADO.NETのデータベース操作を完全マスター
New4
COBOL
COBOLのif文の使い方を完全ガイド!初心者でもわかる条件分岐とネスト
人気記事
No.1
Java&Spring記事人気No1
C#
C#のpartialクラスとは?初心者でも理解できるクラス分割の基本
No.2
Java&Spring記事人気No2
COBOL
COBOLの数値データ型「PIC 9」の使い方と注意点をやさしく解説!
No.3
Java&Spring記事人気No3
C#
C#のラムダ式の書き方と構文を初心者向けに完全解説
No.4
Java&Spring記事人気No4
C#
C#のクエリ式とメソッド式の書き換え方を完全ガイド!LINQの2つの書き方をマスター
No.5
Java&Spring記事人気No5
COBOL
COBOLのCOPY句の使い方を完全ガイド!初心者でもわかる共通部品の再利用方法
No.6
Java&Spring記事人気No6
C#
C#でデータを取得する基本!ExecuteReader・ExecuteScalarの違いを初心者向けに解説
No.7
Java&Spring記事人気No7
C#
C#のADO.NETの基礎!SqlConnectionとSqlCommandの使い方を初心者向けに徹底解説
No.8
Java&Spring記事人気No8
C#
C#の引数と戻り値の基本!値を受け渡し・返す仕組みを理解しよう