「C Sharpとデータベース - 結果の取得」の版間の差分

Wiki がページ「SQL Serverの実行結果を取得する」を「SQL Serverの実行結果を取得する(C Sharp)」に、リダイレクトを残さずに移動しました
編集の要約なし
 
(同じ利用者による、間の5版が非表示)
1行目: 1行目:
== 概要 ==
== 概要 ==
C\#でSQL Serverに対してSELECT文を実行する際のサンプルコードを作成した。<br>
C#でSELECT文の実行結果を取得する方法を説明する。<br>
ここでは、下記の2種類を例として取り上げる。<br>
# SELECT文の実行結果をDataTableを用いてまとめて読み込む方法
# SELECT文の実行結果を1行ずつ読み込む方法
<br>
<br>
結果の取得には、主に以下の2つのアプローチが存在する。<br>
<br>
* DataTableを使用して結果を一括で読み込む方法 (DataAdapter.Fill)
*: SELECT文の全結果をメモリ上のDataTableに展開する。
*: データのランダムアクセスが可能であり、シンプルな実装で小~中規模のデータ処理に適する。
*: <br>
* DataReaderを使用して結果を1行ずつ読み込む方法 (ExecuteReader)
*: 前方向のみの読み取り専用カーソルで1行ずつ処理する。
*: メモリ効率が良く、大量データの処理に適する。
*: O/Rマッピングも容易に実装できる。
<br>
また、COUNT等の集計値を取得する場合は、<code>ExecuteScalar</code> メソッドを使用する方法もある。<br>
<br>
各DBMS (SQL Server, Oracle Database, MySQL) では、対応するクラスが異なる。<br>
<br>
* SQL Server
*: SqlDataAdapter / SqlDataReader
* Oracle Database
*: OracleDataAdapter / OracleDataReader
* MySQL
*: MySqlDataAdapter / MySqlDataReader
<br><br>


== まとめて読み込む(DataTable) ==
== SQL Server ==
DataTableへSELECT文の結果を一括で読み込む方法を説明する。この方法は単純で理解しやすい。<br>
==== 一括読み込み (DataTable) ====
DataSetを使用する方法もあるが、DataTableを取り出すためにワンクッション必要となるため、DataTableへ直接代入する方がよい。<br><br>
DataTableへSELECT文の結果を一括で読み込むことができる。<br>
一括でDataTableへ読み込む際は、DataAdapterを使用する。<br>
<br>
 
DataSetを使用する方法もあるが、DataTableを取り出すためにワンクッション必要となるため、DataTableへ直接代入する方がよい。<br>
<br>
一括でDataTableへ読み込むには、SqlDataAdapterを使用する。<br>
<br>
<syntaxhighlight lang="c#">
  using System;
  using System;
  using System.Configuration;
  using System.Configuration;
  using System.Data;
  using System.Data;
  using System.Data.SqlClient;
  using System.Data.SqlClient;
 
  public DataTable GetData()
  public DataTable GetData()
  {
  {
     var table = new DataTable();
     var table = new DataTable();
 
    // 接続文字列の取得
    var connectionString = ConfigurationManager.ConnectionStrings["sqlsvr"].ConnectionString;
 
    using (var connection = new SqlConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
      try
      {
          // データベースの接続開始
          connection.Open();
 
          // クエリの作成
          command.CommandText = @"SELECT ID, PASSWORD, ROLE_NAME FROM T_USER";
 
          // クエリの実行
          var adapter = new SqlDataAdapter(command);
          adapter.Fill(table);
      }
      catch (Exception exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          // データベースの接続終了
          connection.Close();
      }
    }
 
    return table;
}
</syntaxhighlight>
<br>
==== 1行ずつ読み込む (SqlDataReader) ====
SELECT文の結果を1行ずつ読み込む場合、SqlDataReaderを使用する。<br>
Commandの <code>ExecuteReader()</code> メソッドを実行することで、SqlDataReaderを取得し、1行ずつ読み込んで処理を行う。<br>
<br>
実装はDataTable方式より手間がかかるが、O/Rマッピングのような処理が容易に実装できる。<br>
<br>
以下の例では、UserクラスはT_USERテーブルに対応する独自のモデルクラスである。<br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
// T_USERテーブルに対応するモデルクラス
public class User
{
    public string Id      { get; set; }
    public string Password { get; set; }
    public string RoleName { get; set; }
}
public List<User> GetData()
{
    var list = new List<User>();
   
   
     // 接続文字列の取得
     // 接続文字列の取得
27行目: 109行目:
     using (var command = connection.CreateCommand())
     using (var command = connection.CreateCommand())
     {
     {
        try
      try
        {
      {
            // データベースの接続開始
          // データベースの接続開始
            connection.Open();
          connection.Open();
          // クエリの作成
          command.CommandText = @"SELECT ID, PASSWORD, ROLE_NAME FROM T_USER";
          // クエリの実行
          using (var reader = command.ExecuteReader())
          {
            while (reader.Read())
            {
                list.Add(new User()
                {
                  Id = reader["ID"] as string,
                  Password = reader["PASSWORD"] as string,
                  RoleName = reader["ROLE_NAME"] as string
                });
            }
          }
      }
      catch (Exception exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          // データベースの接続終了
          connection.Close();
      }
    }
    return list;
}
</syntaxhighlight>
<br>
==== 単一値の取得 (ExecuteScalar) ====
COUNT等の集計値のように単一の値を取得する場合は、<code>ExecuteScalar</code> メソッドを使用する。<br>
<br>
ExecuteScalarは、結果セットの最初の行の最初の列を返す。<br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.Configuration;
using System.Data.SqlClient;
public int GetUserCount()
{
    var connectionString = ConfigurationManager.ConnectionStrings["sqlsvr"].ConnectionString;
    using (var connection = new SqlConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
      try
      {
          connection.Open();
          command.CommandText = @"SELECT COUNT(*) FROM T_USER";
          var count = (int)command.ExecuteScalar();
          return count;
      }
      catch (Exception exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          connection.Close();
      }
    }
}
</syntaxhighlight>
<br><br>
 
== Oracle Database ==
Oracle Databaseに対してSELECT文を実行し、結果を取得する。<br>
<br>
Oracle Databaseへのアクセスには、Oracle.ManagedDataAccess.Client 名前空間のクラスを使用する。<br>
<br>
==== 一括読み込み (DataTable) ====
OracleDataAdapterを使用して、SELECT文の結果をDataTableに一括で読み込む。<br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.Configuration;
using System.Data;
using Oracle.ManagedDataAccess.Client;
   
   
            // クエリの作成
public DataTable GetData()
            command.CommandText = @"SELECT count(*) FROM T_USER";
{
    var table = new DataTable();
    var connectionString = ConfigurationManager.ConnectionStrings["oracle"].ConnectionString;
   
   
            // クエリの実行
    using (var connection = new OracleConnection(connectionString))
            var adapter = new SqlDataAdapter(command);
    using (var command = connection.CreateCommand())
            adapter.Fill(table);
    {
        }
      try
        catch (Exception exception)
      {
        {
          connection.Open();
            Console.WriteLine(exception.Message);
          command.CommandText = @"SELECT ID, PASSWORD, ROLE_NAME FROM T_USER";
            throw;
          var adapter = new OracleDataAdapter(command);
        }
          adapter.Fill(table);
        finally
      }
        {   // データベースの接続終了
      catch (OracleException exception)
            connection.Close();
      {
        }
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          connection.Close();
      }
     }
     }
   
   
     return table;
     return table;
  }
  }
</syntaxhighlight>
<br>
==== 1行ずつ読み込む (OracleDataReader) ====
OracleDataReaderを使用して、SELECT文の結果を1行ずつ読み込む。<br>
<br>
<br>
 
<syntaxhighlight lang="c#">
== 1行ずつ読み込む(SqlDataReader) ==
SELECT文の結果を1行ずつ読み込む場合、DataReaderを使用する。<br>
CommandのExecuteReader()メソッドを実行することで、DataReaderを取得し、1行ずつ読み込んで処理を行う。<br>
実装は面倒だが O/Rマッピングのようなことができる。<br><br>
以下のサンプルコードにおけるUserModelはT_USERに対応する独自のクラスになる。<br>
 
  using System;
  using System;
  using System.Collections.Generic;
  using System.Collections.Generic;
  using System.Configuration;
  using System.Configuration;
  using System.Data.SqlClient;
using Oracle.ManagedDataAccess.Client;
  using WebApplication1.Models;
public List<User> GetData()
{
    var list = new List<User>();
    var connectionString = ConfigurationManager.ConnectionStrings["oracle"].ConnectionString;
    using (var connection = new OracleConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
      try
      {
          connection.Open();
          command.CommandText = @"SELECT ID, PASSWORD, ROLE_NAME FROM T_USER";
          using (var reader = command.ExecuteReader())
          {
            while (reader.Read())
            {
                list.Add(new User()
                {
                  Id = reader["ID"].ToString(),
                  Password = reader["PASSWORD"].ToString(),
                  RoleName = reader["ROLE_NAME"].ToString()
                });
            }
          }
      }
      catch (OracleException exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          connection.Close();
      }
    }
    return list;
}
</syntaxhighlight>
<br>
==== 単一値の取得 (ExecuteScalar) ====
OracleCommandのExecuteScalarメソッドを使用して、COUNT等の集計値を取得する。<br>
<br>
<u>OracleのNUMBER型は、decimalにキャストする点に注意が必要である。</u><br>
<br>
<syntaxhighlight lang="c#">
using System;
  using System.Configuration;
  using Oracle.ManagedDataAccess.Client;
   
   
  public List<usermodel> GetData()
  public int GetUserCount()
  {
  {
     var list = new List<usermodel>();
     var connectionString = ConfigurationManager.ConnectionStrings["oracle"].ConnectionString;
   
   
     // 接続文字列の取得
     using (var connection = new OracleConnection(connectionString))
     var connectionString = ConfigurationManager.ConnectionStrings["sqlsvr"].ConnectionString;
    using (var command = connection.CreateCommand())
    {
      try
      {
          connection.Open();
          command.CommandText = @"SELECT COUNT(*) FROM T_USER";
          var count = (int)(decimal)command.ExecuteScalar();
          return count;
      }
      catch (OracleException exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          connection.Close();
      }
    }
}
</syntaxhighlight>
<br><br>
 
== MySQL ==
MySQLに対してSELECT文を実行し、結果を取得する。<br>
<br>
MySQLへのアクセスには、MySqlConnectorパッケージの <code>MySqlConnector</code> 名前空間のクラスを使用する。<br>
<br>
==== 一括読み込み (DataTable) ====
MySqlDataAdapterを使用して、SELECT文の結果をDataTableに一括で読み込む。<br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.Configuration;
using System.Data;
using MySqlConnector;
public DataTable GetData()
{
    var table = new DataTable();
     var connectionString = ConfigurationManager.ConnectionStrings["mysql"].ConnectionString;
   
   
     using (var connection = new SqlConnection(connectionString))
     using (var connection = new MySqlConnection(connectionString))
     using (var command = connection.CreateCommand())
     using (var command = connection.CreateCommand())
     {
     {
        try
      try
        {
      {
            // データベースの接続開始
          connection.Open();
            connection.Open();
          command.CommandText = @"SELECT ID, PASSWORD, ROLE_NAME FROM T_USER";
          var adapter = new MySqlDataAdapter(command);
          adapter.Fill(table);
      }
      catch (MySqlException exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          connection.Close();
      }
    }
   
   
            // クエリの作成
    return table;
            command.CommandText = @"SELECT ID,PASSWORD,ROLE_NAME FROM T_USER";
}
</syntaxhighlight>
<br>
==== 1行ずつ読み込む (MySqlDataReader) ====
MySqlDataReaderを使用して、SELECT文の結果を1行ずつ読み込む。<br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.Collections.Generic;
using System.Configuration;
using MySqlConnector;
public List<User> GetData()
{
    var list = new List<User>();
    var connectionString = ConfigurationManager.ConnectionStrings["mysql"].ConnectionString;
    using (var connection = new MySqlConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
      try
      {
          connection.Open();
          command.CommandText = @"SELECT ID, PASSWORD, ROLE_NAME FROM T_USER";
   
   
            // クエリの実行
          using (var reader = command.ExecuteReader())
            using (var reader = command.ExecuteReader())
          {
            {
            while (reader.Read())
                while (reader.Read() == true)
            {
                list.Add(new User()
                 {
                 {
                    list.Add(new UserModel()
                  Id = reader["ID"].ToString(),
                    {
                  Password = reader["PASSWORD"].ToString(),
                        Id = reader["ID"] as string,
                  RoleName = reader["ROLE_NAME"].ToString()
                        Password = reader["PASSWORD"] as string,
                });
                        RoleName = reader["ROLE_NAME"] as string
            }
                    });
          }
                }
      }
            }
      catch (MySqlException exception)
        }
      {
        catch (Exception exception)
          Console.WriteLine(exception.Message);
        {
          throw;
            Console.WriteLine(exception.Message);
      }
            throw;
      finally
        }
      {
        finally
          connection.Close();
        {   // データベースの接続終了
      }
            connection.Close();
        }
     }
     }
   
   
     return list;
     return list;
  }
  }
</syntaxhighlight>
<br>
==== 単一値の取得 (ExecuteScalar) ====
MySqlCommandの <code>ExecuteScalar</code> メソッドを使用して、COUNT等の集計値を取得する。<br>
<br>
<u>MySQLのCOUNT(*)はlong型で返るため、longにキャストする点に注意が必要である。</u><br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.Configuration;
using MySqlConnector;
public long GetUserCount()
{
    var connectionString = ConfigurationManager.ConnectionStrings["mysql"].ConnectionString;
    using (var connection = new MySqlConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
      try
      {
          connection.Open();
          command.CommandText = @"SELECT COUNT(*) FROM T_USER";
          var count = (long)command.ExecuteScalar();
          return count;
      }
      catch (MySqlException exception)
      {
          Console.WriteLine(exception.Message);
          throw;
      }
      finally
      {
          connection.Close();
      }
    }
}
</syntaxhighlight>
<br><br>
== DataTableとDataReaderの比較 ==
DataTable (DataAdapter) 方式 と DataReader方式の特徴を下表に示す。<br>
<br>
<center>
{| class="wikitable"
|+ DataTableとDataReaderの比較
! 項目 !! DataTable (DataAdapter) !! DataReader
|-
| 読み込み方式 || 一括読み込み || 1行ずつ読み込み
|-
| メモリ使用量 || 全データをメモリに展開 || 現在行のみメモリに保持
|-
| アクセス方向 || ランダムアクセス可能 || 前方向のみ
|-
| 接続 || Fill後に接続クローズ可能 || 読み込み中は接続維持が必要
|-
| 適したデータ量 || 小〜中規模 || 大規模
|-
| O/Rマッピング || 不向き || 容易
|}
</center>
<br><br>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:C_Sharp]]
[[カテゴリ:C_Sharp]]