こんにちは。明月です。
この投稿はC#でデータベース(MSSQL)に接続する方法に関する説明です。
我々がプログラムを作成すればデータを格納する場合が多いですが、IOを利用するファイルで格納する方法やSocketサーバを利用して他のPCやプログラムを利用して格納する方法などの様々な方法があります。
でも、データを格納する方法で一番しやすいし、検索やフィルターする方法でデータベースを利用する方法があります。
データベースの種類はすごく多いですが、その中でOracle(オラクル)、MsSQL(Sql-server)、MySqlあるいはMariaDBがよく使うデータベースです。
その中でMsSQLはMS(Microsoft)社で提供するデータベースだし、C#もMS(Microsoft)社で提供するプログラム言語なのでC#では他のデータベースよりMsSQLが扱いしやすいです。扱いしやすいより別途のライブラリがなくても使えるデータベースです。
まず、データベースを接続するためにはデータベースをインストールしなければならないですが、それは別途の投稿で説明します。
link - 予定
データベースがインストールされたら簡単なテーブルを作成してC#プログラムで検索してみましょう。
-- drop table Test;
-- テーブル作成
create table Test(
idx int identity(1,1),
data nvarchar(max)
)
-- データインサート
insert into Test values('Hello world - 1');
insert into Test values('Hello world - 2');
insert into Test values('Hello world - 3');
insert into Test values('Hello world - 4');
insert into Test values('Hello world - 5');
insert into Test values('Hello world - 6');
insert into Test values('Hello world - 7');
insert into Test values('Hello world - 8');
insert into Test values('Hello world - 9');
insert into Test values('Hello world - 10');
insert into Test values('Hello world - 11');
insert into Test values('Hello world - 12');
-- 検索
select * from Test;
上の例みたいにデータベースでテーブルを作成して簡単なデータを入力しました。
このデータを利用してC#プログラムでデータを取得しましょう。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// SqlCommandクラスのインスタンス生成
var cmd = new SqlCommand();
// 接続コネクションを生成する。
cmd.Connection = new SqlConnection("Data Source=localhost;Database=BlogExample;User Id=sa;Password=");
// 検索するクエリを入れる。
cmd.CommandText = "select * from Test";
// 検索クエリタイプ、一般クエリはTextだし、プロシージャはStoredProcedureだ。
cmd.CommandType = CommandType.Text;
// 検索して格納するデータ変数
List<List<object>> dataList = null;
// 検索したテーブルのColumn変数
string[] fieldList = null;
// Close設定(スタック領域が終わったら、自動にコネクション終了)
using (cmd.Connection)
{
// コネクション Open
cmd.Connection.Open();
// 上のクエリを接続してSqlDataReaderを取得
var dr = cmd.ExecuteReader();
// データ変数のインスタンス生成
dataList = new List<List<object>>();
// Column変数のインスタンス生成
fieldList = new string[dr.FieldCount];
// テーブルのフィールドほど
for (var i = 0; i < fieldList.Length; i++)
{
// フィールド名を配列に格納
fieldList[i] = dr.GetName(i);
}
// レコードの個数程にループ
while (dr.Read())
{
// レコードデータを格納する変数リストを生成
var entity = new List<object>();
// データ変数リストに格納
dataList.Add(entity);
// Columnのサイズ程
for (var i = 0; i < fieldList.Length; i++)
{
// カラムのタイプを取得
var type = dr.GetFieldType(i);
// intタイプなら
if (type == typeof(int))
{
// intタイプで取得
entity.Add(dr.GetInt32(i));
}
// stringタイプなら
else if (type == typeof(string))
{
// stringタイプで取得
entity.Add(dr.GetString(i));
}
else
{
// objectタイプで取得
entity.Add(dr.GetValue(i));
}
}
}
}
// コンソールにヘッダーにColumn名を出力する。
foreach (var field in fieldList)
{
// コンソール出力
Console.Write(field);
// tabの二つをコンソールに出力
Console.Write("\t\t");
}
// 改行
Console.WriteLine();
// テーブルColumn名とデータを区分するため、コンソール出力
for (int i = 0; i < fieldList.Length; i++)
{
// コンソール出力
Console.Write("-----------------");
}
// 改行
Console.WriteLine();
// データのサイズ程
foreach (var entity in dataList)
{
// Columnのサイズ程
foreach (var column in entity)
{
// コンソール出力
Console.Write(column);
// tabの二つをコンソールに出力
Console.Write("\t\t");
}
// 改行
Console.WriteLine();
}
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
上の例をみればデータベースにあるTestのテーブルのデータを読み込んでコンソールに出力しました。
SqlCommandクラスのインスタンスを生成してコネクションを作ってExecuteReaderの関数を実行してデータを読み込みました。
そしてExecuteReaderの関数のリターン値はSqlDataReaderのインスタンスだし、SqlDataReaderのRead関数を利用してデータを読み込みました。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// SqlCommandクラスのインスタンス生成
var cmd = new SqlCommand();
// 接続コネクションを生成する。
cmd.Connection = new SqlConnection("Data Source=localhost;Database=BlogExample;User Id=sa;Password=");
// 検索クエリタイプ、一般クエリはTextだし、プロシージャはStoredProcedureだ。
cmd.CommandType = CommandType.Text;
// 検索して格納するデータ変数
List<List<object>> dataList = null;
// 検索したテーブルのColumn変数
string[] fieldList = null;
// Close設定(スタック領域が終わったら、自動にコネクション終了)
using (cmd.Connection)
{
// コネクション Open
cmd.Connection.Open();
// データ削除クエリ
cmd.CommandText = "delete Test";
// 実行(リターン値が必要ない。)
cmd.ExecuteNonQuery();
// データ追加クエリ
cmd.CommandText = "insert into Test values(@data)";
// @dataパラメータにデータを入力する。
cmd.Parameters.Add(new SqlParameter("@data", "Hello world - Addition"));
// 実行(リターン値が必要ない。)
cmd.ExecuteNonQuery();
// 検索するクエリを入れる。
cmd.CommandText = "select * from Test";
// 上のクエリを接続してSqlDataReaderを取得
var dr = cmd.ExecuteReader();
// データ変数のインスタンス生成
dataList = new List<List<object>>();
// Column変数のインスタンス生成
fieldList = new string[dr.FieldCount];
// テーブルのフィールドほど
for (var i = 0; i < fieldList.Length; i++)
{
// フィールド名を配列に格納
fieldList[i] = dr.GetName(i);
}
// レコードの個数程にループ
while (dr.Read())
{
// レコードデータを格納する変数リストを生成
var entity = new List<object>();
// データ変数リストに格納
dataList.Add(entity);
// Columnのサイズ程
for (var i = 0; i < fieldList.Length; i++)
{
// カラムのタイプを取得
var type = dr.GetFieldType(i);
// intタイプなら
if (type == typeof(int))
{
// intタイプで取得
entity.Add(dr.GetInt32(i));
}
// stringタイプなら
else if (type == typeof(string))
{
// stringタイプで取得
entity.Add(dr.GetString(i));
}
else
{
// objectタイプで取得
entity.Add(dr.GetValue(i));
}
}
}
}
// コンソールにヘッダーにColumn名を出力する。
foreach (var field in fieldList)
{
// コンソール出力
Console.Write(field);
// tabの二つをコンソールに出力
Console.Write("\t\t");
}
// 改行
Console.WriteLine();
// テーブルColumn名とデータを区分するため、コンソール出力
for (int i = 0; i < fieldList.Length; i++)
{
// コンソール出力
Console.Write("-----------------");
}
// 改行
Console.WriteLine();
// データのサイズ程
foreach (var entity in dataList)
{
// Columnのサイズ程
foreach (var column in entity)
{
// コンソール出力
Console.Write(column);
// tabの二つをコンソールに出力
Console.Write("\t\t");
}
// 改行
Console.WriteLine();
}
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
上の例ではdeleteとinsertをしてデータを削除と追加しました。
そして関数はExecuteReaderの関数ではなく、ExecuteNonQueryの関数を使って実行しました。
なぜならdeleteとinsertは検索の結果を取得することではなく、実行だけが重要だからです。
上の方法は連結指向タイプのデータベース接続だといいます。つまり、データベースからデータを一括に取得することではなく、Read()関数を通って一つ一つに取得することです。連結指向タイプでシステムに関する負担は少ないと思いますが、データが多いなら、データベースのlockやトランザクションに問題がある可能性があります。
そのため、レコードを一つ一つに読み込む連結指向タイプではなく、データを一括に取得する非連結指向タイプの接続方法もあります。
using System;
using System.Data;
using System.Data.SqlClient;
namespace Example
{
class Program
{
// 実行関数
static void Main(string[] args)
{
// SqlDataAdapterインスタンス生成
var sda = new SqlDataAdapter();
// SqlCommandクラスのインスタンス生成
sda.SelectCommand = new SqlCommand();
// 接続コネクションのインスタンスを生成する。
sda.SelectCommand.Connection = new SqlConnection("Data Source=localhost;Database=BlogExample;User Id=sa;Password=");
// 検索したクエリを格納
sda.SelectCommand.CommandText = "select * from Test";
// 検索クエリタイプ、一般クエリはTextだし、プロシージャはStoredProcedureだ。
sda.SelectCommand.CommandType = CommandType.Text;
// DataSetインスタンスを生成
var ds = new DataSet();
// SqlDataAdapterインスタンスにDataSetデータを入れる。
sda.Fill(ds);
// 検索したテーブル個数程
foreach (DataTable table in ds.Tables)
{
// コンソールにヘッダーにColumn名を出力する。
foreach (DataColumn column in table.Columns)
{
// コンソール出力
Console.Write(column.ColumnName);
// tabの二つをコンソールに出力
Console.Write("\t\t");
}
// 改行
Console.WriteLine();
// テーブルColumn名とデータを区分するため、コンソール出力
for (int i = 0; i < table.Columns.Count; i++)
{
// コンソール出力
Console.Write("-----------------");
}
// 改行
Console.WriteLine();
// テーブルのレコード個数程
foreach (DataRow row in table.Rows)
{
// Columnのサイズ程
foreach (DataColumn column in table.Columns)
{
// コンソールに出力
Console.Write(row[column]);
// tabの二つをコンソールに出力
Console.Write("\t\t");
}
// 改行
Console.WriteLine();
}
}
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
結果は連結指向タイプでデータを取得することと同じです。データベースからデータを取得した結果は同じですが、データを取得する方法に関する差異があります。
この場合はデータを一括で取得してDataSetに格納するので、データが多くなるとプログラム側に多いインスタンス生成により逆に遅くなるしメモリ負担になります。代わりにデータベースには一括にSelectして結果を送信した後なので、負担がないですね。
仕様に合わせて連結指向タイプで実装するか非連結指向タイプに実装するかを決めたら良いです。
ここまでC#でデータベース(MSSQL)に接続する方法に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [C#] 53. Reflection機能を使い方 - Propertyとevent2021/10/19 21:02:58
- [C#] 52. Reflection機能を使い方 - Variable2021/10/15 19:27:37
- [C#] 51. Reflection機能を使い方 - Method2021/10/14 18:34:21
- [C#] 50. Reflection機能を使い方 - Class2021/10/13 18:34:13
- [C#] 49. Operator(演算子)のオーバーロードを使い方2021/10/12 18:28:42
- [C#] 48. IEnumerableとIEnumerator、そしてyieldキーワード2021/10/11 19:49:33
- [C#] 47. Nugetを使い方(外部ライブラリ)とデータベース(MariaDB(Mysql))を使い方、そしてトランザクション(Transaction)2021/10/08 18:58:57
- [C#] 46. データベース(MSSQL)に接続する方法2021/10/07 18:39:58
- [C#] 45. ネットワークソケット通信(Socket)を使い方2021/10/06 19:06:25
- [C#] 44. ファイル(FileInfo)とディレクトリ(DirectoryInfo)を扱い2021/10/05 19:29:34
- [C#] 43. ストリーム(Stream)とバイナリ(byte[])、エンコード(Encoding)、そしてusingを使い方とIDisposableインターフェース2021/10/04 18:33:04
- [C#] 42. ファイルを扱い(IO)とファイルメタデータ(FileInfo)を使い方2021/10/01 20:10:21
- [C#] 41. Taskクラスとasync、awaitを使い方2021/10/01 18:59:14
- [C#] 40. Linqを利用した並列処理(Parallel)を使い方2020/05/13 17:37:13
- [C#] 39. lockキーワードとdeadlock(デッドロック)2019/07/24 00:57:35
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07