C#でデータベース接続・CRUDを実装する方法|初心者向けにSQL Server・SQLite・EF Coreまで解説

はじめに

C#でアプリケーションを作るとき、多くの場合でデータベースとの連携が必要になります。たとえば、ユーザー情報を保存する、商品一覧を表示する、入力されたデータを更新する、不要なレコードを削除するといった処理です。

C#でデータベースを扱う方法はいくつかあります。代表的なのは、SQLを直接実行する ADO.NET、軽量なファイル型データベースである SQLite、オブジェクト指向でデータベースを操作できる Entity Framework Core(EF Core) です。

この記事では、初心者向けに「C# データベース」の基礎から、SQL Server・SQLiteへの接続方法、CRUD処理、EF Coreを使った実装、安全に扱うためのポイントまで順番に解説します。

1. C#でデータベースを扱う前に知っておきたい基礎知識

1-1. C#からデータベースに接続してできること

C#からデータベースに接続すると、アプリケーション内のデータを永続的に保存できます。

たとえば、コンソールアプリ、Windowsアプリ、Webアプリなどからデータベースへ接続し、次のような処理を実行できます。

  • ユーザー情報を登録する

  • 商品データを一覧表示する

  • 注文情報を更新する

  • ログや履歴を保存する

  • 不要なデータを削除する

  • 条件に一致するデータを検索する

変数や配列に保存したデータは、アプリケーションを終了すると基本的に消えてしまいます。しかし、データベースに保存すれば、アプリを終了してもデータを残せます。

そのため、C#で実用的なアプリケーションを作るなら、データベース接続の知識は非常に重要です。

1-2. CRUDとは?Create・Read・Update・Deleteの基本

データベース操作の基本は CRUD です。

CRUDとは、次の4つの処理を表します。

操作意味SQL
Createデータを追加するINSERT
Readデータを取得するSELECT
Updateデータを更新するUPDATE
Deleteデータを削除するDELETE

たとえば、ユーザー情報を扱う場合は次のようになります。

  • Create:新しいユーザーを登録する

  • Read:登録済みユーザーを一覧表示する

  • Update:ユーザー名やメールアドレスを変更する

  • Delete:退会したユーザーを削除する

C#でデータベースを扱う学習では、まずCRUDを理解することが重要です。CRUDがわかれば、ほとんどの業務アプリやWebアプリの基本的なデータ操作を実装できるようになります。

1-3. SQL Server・SQLite・EF Coreの違い

C#でデータベースを扱うときによく使われるものに、SQL Server、SQLite、EF Coreがあります。

SQL Server は、Microsoftが提供する本格的なリレーショナルデータベースです。企業の業務システムやWebシステムでもよく使われます。C#や.NETとの相性がよく、Visual StudioやAzureとも連携しやすいのが特徴です。

SQLite は、サーバーを立てずに使える軽量なデータベースです。データは1つのファイルとして保存されます。小規模アプリ、学習用、ローカルツール、スマホアプリなどでよく使われます。

Entity Framework Core は、データベースそのものではなく、C#からデータベースを操作しやすくするためのORMです。ORMとは、テーブルのデータをC#のクラスやオブジェクトとして扱える仕組みです。

簡単に整理すると、次のようになります。

種類役割特徴
SQL Serverデータベース本格的なシステム向け
SQLiteデータベース軽量で学習しやすい
EF CoreORMC#のコードでDB操作しやすい

1-4. 初心者はどれを選ぶべきか

初心者がC#でデータベースを学ぶなら、最初は SQLite がおすすめです。

SQLiteはインストールやサーバー設定が少なく、データベースファイルを作るだけで始められます。接続文字列もシンプルなので、C#からデータベースへ接続する流れを理解しやすいです。

次に、SQL Serverを使って本格的なデータベース接続を学ぶとよいでしょう。SQL Serverは実務でも使われることが多く、LocalDBを使えばローカル環境でも比較的簡単に試せます。

その後、EF Coreを学ぶと、C#らしい書き方で効率よくCRUDを実装できるようになります。

おすすめの学習順序は次のとおりです。

  1. SQLiteでCRUDの流れを理解する

  2. SQL Serverで接続文字列やSQL実行を学ぶ

  3. EF CoreでORMによる実装を覚える

  4. Webアプリや業務アプリに応用する

2. C#でデータベース接続する主な方法

2-1. ADO.NETで直接SQLを実行する方法

ADO.NETは、C#からデータベースへ接続し、SQLを直接実行するための基本的な仕組みです。

ADO.NETでは、主に次のクラスを使います。

  • Connection:データベースへ接続する

  • Command:SQLを実行する

  • DataReader:SELECT結果を読み取る

  • Parameter:SQLに値を安全に渡す

SQL Serverの場合は、主に SqlConnectionSqlCommand を使います。

C#
using Microsoft.Data.SqlClient;

var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

using var connection = new SqlConnection(connectionString);
connection.Open();

var sql = "SELECT Id, Name FROM Users";

using var command = new SqlCommand(sql, connection);
using var reader = command.ExecuteReader();

while (reader.Read())
{
Console.WriteLine($"{reader["Id"]}: {reader["Name"]}");
}

ADO.NETはSQLを直接書くため、データベースの仕組みを理解しやすいというメリットがあります。一方で、コード量が多くなりやすい点には注意が必要です。

2-2. Entity Framework CoreでORMとして操作する方法

Entity Framework Core、略してEF Coreは、C#のクラスを使ってデータベースを操作できるORMです。

通常、SQLでデータを取得する場合は次のように書きます。

SQL
SELECT * FROM Users WHERE Id = 1;

EF Coreでは、次のようにC#のコードで書けます。

C#
var user = context.Users.FirstOrDefault(u => u.Id == 1);

EF Coreを使うと、SQLを毎回直接書かなくても、LINQを使ってデータを検索・追加・更新・削除できます。

たとえば、データ追加は次のように書けます。

C#
context.Users.Add(new User { Name = "Taro", Email = "taro@example.com" });
context.SaveChanges();

EF Coreは、Webアプリや業務アプリなど、ある程度規模のある開発で便利です。ただし、裏側でどのようなSQLが発行されるかを理解しておくことも大切です。

2-3. SQL ServerとSQLiteで接続方法が異なる理由

SQL ServerとSQLiteでは、データベースの仕組みが異なります。

SQL Serverは、データベースサーバーに接続して利用します。そのため、接続文字列にはサーバー名、データベース名、認証情報などを指定します。

Server=(localdb)\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;

一方、SQLiteはデータベースファイルに直接接続します。そのため、接続文字列にはファイルパスを指定します。

Data Source=sample.db

この違いにより、C#側で使うパッケージや接続クラスも異なります。

SQL Serverでは Microsoft.Data.SqlClient を使い、SQLiteでは Microsoft.Data.Sqlite を使います。

2-4. 接続文字列とは何か

接続文字列とは、C#アプリケーションがデータベースに接続するために必要な情報をまとめた文字列です。

SQL Serverの接続文字列の例です。

C#
var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

SQLiteの接続文字列の例です。

C#
var connectionString = "Data Source=sample.db";

接続文字列には、主に次のような情報を指定します。

  • 接続先サーバー

  • データベース名

  • ユーザー名

  • パスワード

  • DBファイルの場所

  • 認証方式

接続文字列が間違っていると、C#からデータベースに接続できません。初心者がつまずきやすいポイントなので、エラーが出たときはまず接続文字列を確認しましょう。

3. 開発環境の準備

3-1. Visual Studioまたは.NET SDKを用意する

C#でデータベース接続を試すには、まずC#を実行できる環境を用意します。

初心者には、Visual Studioを使う方法がおすすめです。プロジェクト作成、NuGetパッケージ管理、デバッグなどを画面上で操作できるためです。

コマンド操作に慣れている場合は、.NET SDKをインストールしてターミナルから作業しても問題ありません。

この記事では、コンソールアプリを例にして解説します。コンソールアプリなら、画面設計を気にせずデータベース接続とCRUD処理に集中できます。

3-2. コンソールアプリを作成する

.NET CLIを使う場合は、次のコマンドでコンソールアプリを作成できます。

Bash
dotnet new console -n CSharpDatabaseSample
cd CSharpDatabaseSample

Visual Studioを使う場合は、次の手順で作成します。

  1. Visual Studioを起動する

  2. 「新しいプロジェクトの作成」を選択する

  3. 「コンソール アプリ」を選択する

  4. プロジェクト名を入力する

  5. 作成をクリックする

これで、C#のコードを実行する準備ができます。

3-3. NuGetパッケージをインストールする

C#からSQL ServerやSQLiteに接続するには、必要なNuGetパッケージを追加します。

SQL Serverを使う場合は、次のパッケージを追加します。

Bash
dotnet add package Microsoft.Data.SqlClient

SQLiteを使う場合は、次のパッケージを追加します。

Bash
dotnet add package Microsoft.Data.Sqlite

EF CoreでSQLiteを使う場合は、次のパッケージを追加します。

Bash
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design

EF CoreでSQL Serverを使う場合は、次のパッケージを追加します。

Bash
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design

NuGetパッケージが不足していると、SqlConnectionSqliteConnectionDbContext などのクラスが使えません。

3-4. サンプル用テーブルを作成する

この記事では、ユーザー情報を管理する Users テーブルを例にします。

SQL Server用のテーブル作成SQLは次のとおりです。

SQL
CREATE TABLE Users (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(100) NOT NULL,
Email NVARCHAR(200) NOT NULL
);

SQLite用のテーブル作成SQLは次のとおりです。

SQL
CREATE TABLE Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT NOT NULL
);

SQL ServerとSQLiteでは、データ型や自動採番の書き方が少し異なります。

SQL Serverでは INT IDENTITY(1,1) を使い、SQLiteでは INTEGER PRIMARY KEY AUTOINCREMENT を使います。

4. C#からSQL Serverに接続する方法

4-1. SQL Server・LocalDBを準備する

SQL Serverをローカルで試す場合、初心者にはLocalDBが便利です。

LocalDBは、開発用に使える軽量なSQL Serverです。Visual Studioをインストールしている環境では、すでに利用できる場合があります。

接続文字列の例は次のとおりです。

C#
var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

ここでは、SampleDb というデータベースに接続する想定です。

データベースやテーブルを事前に作成しておくか、SQL Server Management StudioやVisual StudioのSQL Serverオブジェクトエクスプローラーから作成します。

4-2. SqlConnectionで接続する

C#からSQL Serverへ接続するには、SqlConnection を使います。

C#
using Microsoft.Data.SqlClient;

var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

using var connection = new SqlConnection(connectionString);

connection.Open();

Console.WriteLine("SQL Serverに接続しました。");

Open() を実行すると、データベースへの接続が開始されます。

using を使うことで、処理が終わったあとに接続を自動的に閉じられます。データベース接続は開きっぱなしにせず、必要なときだけ開いて、使い終わったら閉じるのが基本です。

4-3. SELECTでデータを取得する

SQL Serverからデータを取得するには、SELECT 文を実行します。

C#
using Microsoft.Data.SqlClient;

var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

using var connection = new SqlConnection(connectionString);
connection.Open();

var sql = "SELECT Id, Name, Email FROM Users";

using var command = new SqlCommand(sql, connection);
using var reader = command.ExecuteReader();

while (reader.Read())
{
var id = reader.GetInt32(0);
var name = reader.GetString(1);
var email = reader.GetString(2);

Console.WriteLine($"{id}: {name} - {email}");
}

ExecuteReader() は、SELECT結果を1行ずつ読み取るために使います。

reader.Read()true の間、取得したレコードを順番に処理できます。

4-4. INSERTでデータを追加する

SQL Serverにデータを追加するには、INSERT 文を実行します。

C#
using Microsoft.Data.SqlClient;

var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

using var connection = new SqlConnection(connectionString);
connection.Open();

var sql = "INSERT INTO Users (Name, Email) VALUES (@Name, @Email)";

using var command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@Name", "Taro");
command.Parameters.AddWithValue("@Email", "taro@example.com");

var rows = command.ExecuteNonQuery();

Console.WriteLine($"{rows}件追加しました。");

ExecuteNonQuery() は、INSERT、UPDATE、DELETEのように結果セットを返さないSQLを実行するときに使います。

ここでは、SQLに直接値を埋め込まず、@Name@Email というパラメータを使っています。これはSQLインジェクション対策として重要です。

4-5. UPDATEでデータを更新する

データを更新するには、UPDATE 文を使います。

C#
using Microsoft.Data.SqlClient;

var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

using var connection = new SqlConnection(connectionString);
connection.Open();

var sql = "UPDATE Users SET Email = @Email WHERE Id = @Id";

using var command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@Email", "new-taro@example.com");
command.Parameters.AddWithValue("@Id", 1);

var rows = command.ExecuteNonQuery();

Console.WriteLine($"{rows}件更新しました。");

WHERE Id = @Id を書かないと、すべてのレコードが更新される可能性があります。

UPDATEやDELETEを実行するときは、必ず条件を確認しましょう。

4-6. DELETEでデータを削除する

データを削除するには、DELETE 文を使います。

C#
using Microsoft.Data.SqlClient;

var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

using var connection = new SqlConnection(connectionString);
connection.Open();

var sql = "DELETE FROM Users WHERE Id = @Id";

using var command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@Id", 1);

var rows = command.ExecuteNonQuery();

Console.WriteLine($"{rows}件削除しました。");

DELETEもUPDATEと同じく、WHERE 条件が重要です。

条件なしで次のように書くと、テーブル内のすべてのデータが削除されます。

SQL
DELETE FROM Users;

実務では非常に危険なので、削除処理では対象データを十分に確認する必要があります。

5. C#からSQLiteに接続する方法

5-1. SQLiteを使うメリット

SQLiteは、C#でデータベースを学ぶ初心者に向いています。

主なメリットは次のとおりです。

  • サーバーのインストールが不要

  • データベースが1つのファイルで管理できる

  • 接続文字列がシンプル

  • 小規模アプリや学習用に使いやすい

  • コンソールアプリでもすぐ試せる

SQL Serverのようにサーバーを起動したり、認証設定をしたりする必要が少ないため、C#のデータベース接続を初めて学ぶ場合におすすめです。

5-2. SQLite用パッケージを追加する

C#からSQLiteを使うには、Microsoft.Data.Sqlite を追加します。

Bash
dotnet add package Microsoft.Data.Sqlite

コードでは、次の名前空間を使います。

C#
using Microsoft.Data.Sqlite;

SQL Serverでは Microsoft.Data.SqlClient を使いましたが、SQLiteでは Microsoft.Data.Sqlite を使います。

5-3. データベースファイルを作成する

SQLiteでは、データベースをファイルとして扱います。

接続文字列で次のように指定すると、sample.db というファイルを使います。

C#
var connectionString = "Data Source=sample.db";

ファイルが存在しない場合は、接続時に作成されます。

ただし、テーブルは自動では作られないため、最初に CREATE TABLE を実行する必要があります。

C#
using Microsoft.Data.Sqlite;

var connectionString = "Data Source=sample.db";

using var connection = new SqliteConnection(connectionString);
connection.Open();

var sql = @"
CREATE TABLE IF NOT EXISTS Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT NOT NULL
);";

using var command = new SqliteCommand(sql, connection);
command.ExecuteNonQuery();

Console.WriteLine("テーブルを作成しました。");

CREATE TABLE IF NOT EXISTS を使うと、テーブルが存在しない場合だけ作成できます。

5-4. SQLiteConnectionで接続する

SQLiteに接続するには、SqliteConnection を使います。

C#
using Microsoft.Data.Sqlite;

var connectionString = "Data Source=sample.db";

using var connection = new SqliteConnection(connectionString);
connection.Open();

Console.WriteLine("SQLiteに接続しました。");

SQL Serverの SqlConnection と似た書き方ですが、クラス名と接続文字列が異なります。

SQLiteの場合は、ファイルパスの指定ミスに注意しましょう。相対パスで指定した場合、実行時のカレントディレクトリにDBファイルが作成されることがあります。

5-5. SQLiteでCRUD処理を実装する

SQLiteでCRUDをまとめて実装すると、次のようになります。

C#
using Microsoft.Data.Sqlite;

var connectionString = "Data Source=sample.db";

using var connection = new SqliteConnection(connectionString);
connection.Open();

// テーブル作成
var createTableSql = @"
CREATE TABLE IF NOT EXISTS Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT NOT NULL
);";

using (var command = new SqliteCommand(createTableSql, connection))
{
command.ExecuteNonQuery();
}

// Create
var insertSql = "INSERT INTO Users (Name, Email) VALUES (@Name, @Email)";

using (var command = new SqliteCommand(insertSql, connection))
{
command.Parameters.AddWithValue("@Name", "Hanako");
command.Parameters.AddWithValue("@Email", "hanako@example.com");
command.ExecuteNonQuery();
}

// Read
var selectSql = "SELECT Id, Name, Email FROM Users";

using (var command = new SqliteCommand(selectSql, connection))
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"{reader.GetInt32(0)}: {reader.GetString(1)} - {reader.GetString(2)}");
}
}

// Update
var updateSql = "UPDATE Users SET Email = @Email WHERE Name = @Name";

using (var command = new SqliteCommand(updateSql, connection))
{
command.Parameters.AddWithValue("@Email", "new-hanako@example.com");
command.Parameters.AddWithValue("@Name", "Hanako");
command.ExecuteNonQuery();
}

// Delete
var deleteSql = "DELETE FROM Users WHERE Name = @Name";

using (var command = new SqliteCommand(deleteSql, connection))
{
command.Parameters.AddWithValue("@Name", "Hanako");
command.ExecuteNonQuery();
}

このように、SQLiteでもSQL Serverとほぼ同じ流れでCRUDを実装できます。

違いは、接続クラス、接続文字列、SQLのデータ型などです。

6. Entity Framework CoreでCRUDを実装する方法

6-1. EF Coreとは何か

EF Coreは、C#のクラスとデータベースのテーブルを対応させて操作できるORMです。

ADO.NETではSQLを直接書いてデータベースを操作しますが、EF CoreではC#のオブジェクトを操作する感覚でデータを扱えます。

たとえば、次のようなC#クラスを用意します。

C#
public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
}

この User クラスを、データベースの Users テーブルと対応させます。

EF Coreを使うと、次のようなコードでデータを追加できます。

C#
context.Users.Add(new User
{
Name = "Taro",
Email = "taro@example.com"
});

context.SaveChanges();

SQLを直接書く量が減るため、開発効率を高めやすいのが特徴です。

6-2. DbContextとモデルクラスを作成する

EF Coreでは、モデルクラスと DbContext を作成します。

まず、モデルクラスを作成します。

C#
public class User
{
public int Id { get; set; }

public string Name { get; set; } = "";

public string Email { get; set; } = "";
}

次に、DbContext を作成します。

SQLiteを使う場合の例です。

C#
using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
public DbSet<User> Users => Set<User>();

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=efsample.db");
}
}

SQL Serverを使う場合は、UseSqlServer を使います。

C#
using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
public DbSet<User> Users => Set<User>();

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(
"Server=(localdb)\\MSSQLLocalDB;Database=EfSampleDb;Trusted_Connection=True;TrustServerCertificate=True;"
);
}
}

DbSet<User> は、Users テーブルをC#から操作するための入口です。

6-3. マイグレーションでテーブルを作成する

EF Coreでは、マイグレーションを使ってC#のモデルからテーブルを作成できます。

まず、EF Coreのツールを使えるようにします。

Bash
dotnet tool install --global dotnet-ef

すでにインストール済みの場合は、更新します。

Bash
dotnet tool update --global dotnet-ef

次に、マイグレーションを作成します。

Bash
dotnet ef migrations add InitialCreate

その後、データベースへ反映します。

Bash
dotnet ef database update

これにより、User クラスに対応した Users テーブルが作成されます。

マイグレーションを使うと、テーブル構造の変更履歴を管理しやすくなります。実務では、モデルの変更に合わせてマイグレーションを追加していくことが多いです。

6-4. Addでデータを登録する

EF Coreでデータを登録するには、AddSaveChanges を使います。

C#
using var context = new AppDbContext();

var user = new User
{
Name = "Taro",
Email = "taro@example.com"
};

context.Users.Add(user);
context.SaveChanges();

Console.WriteLine("ユーザーを登録しました。");

Add しただけでは、まだデータベースには保存されません。

実際にINSERTを実行するには、SaveChanges() を呼び出します。

複数件まとめて追加する場合は、AddRange を使えます。

C#
context.Users.AddRange(
new User { Name = "Jiro", Email = "jiro@example.com" },
new User { Name = "Saburo", Email = "saburo@example.com" }
);

context.SaveChanges();

6-5. LINQでデータを取得する

EF Coreでは、LINQを使ってデータを取得できます。

全件取得する例です。

C#
using var context = new AppDbContext();

var users = context.Users.ToList();

foreach (var user in users)
{
Console.WriteLine($"{user.Id}: {user.Name} - {user.Email}");
}

条件を指定して取得する例です。

C#
var user = context.Users.FirstOrDefault(u => u.Id == 1);

if (user != null)
{
Console.WriteLine($"{user.Name} - {user.Email}");
}

名前に特定の文字を含むユーザーを検索する例です。

C#
var users = context.Users
.Where(u => u.Name.Contains("Taro"))
.ToList();

EF Coreでは、LINQで書いた処理が内部的にSQLへ変換されて実行されます。

6-6. Updateでデータを更新する

EF Coreでデータを更新するには、まず対象データを取得し、プロパティを変更して SaveChanges を呼び出します。

C#
using var context = new AppDbContext();

var user = context.Users.FirstOrDefault(u => u.Id == 1);

if (user != null)
{
user.Email = "updated@example.com";
context.SaveChanges();

Console.WriteLine("ユーザー情報を更新しました。");
}

EF Coreは、取得したエンティティの変更を追跡しています。そのため、値を変更して SaveChanges() を呼ぶと、必要なUPDATE文が発行されます。

明示的に Update を使うこともできます。

C#
var user = new User
{
Id = 1,
Name = "Taro",
Email = "updated@example.com"
};

context.Users.Update(user);
context.SaveChanges();

ただし、初心者のうちは、まず取得してから変更する方法の方が理解しやすいです。

6-7. Removeでデータを削除する

EF Coreでデータを削除するには、Remove を使います。

C#
using var context = new AppDbContext();

var user = context.Users.FirstOrDefault(u => u.Id == 1);

if (user != null)
{
context.Users.Remove(user);
context.SaveChanges();

Console.WriteLine("ユーザーを削除しました。");
}

複数件削除する場合は、RemoveRange を使います。

C#
var users = context.Users
.Where(u => u.Name == "Taro")
.ToList();

context.Users.RemoveRange(users);
context.SaveChanges();

削除処理は取り消しが難しいため、条件を間違えないように注意しましょう。

7. ADO.NETとEF Coreはどちらを使うべきか

7-1. 初心者がADO.NETで学ぶメリット

初心者がC#でデータベースを学ぶなら、一度はADO.NETでSQLを直接書くことをおすすめします。

ADO.NETを学ぶメリットは次のとおりです。

  • SQLの基本を理解できる

  • 接続、実行、取得の流れがわかる

  • データベースの仕組みを意識しやすい

  • エラーの原因を追いやすくなる

  • EF Coreの裏側の動きを理解しやすくなる

EF Coreは便利ですが、SQLや接続の仕組みを知らないまま使うと、トラブルが起きたときに原因を見つけにくくなります。

そのため、まずADO.NETでCRUDを実装し、SQLの基本を理解してからEF Coreへ進むと学習しやすいです。

7-2. EF Coreを使うメリット

EF Coreを使うメリットは、開発効率の高さです。

SQLを直接書かなくても、C#のクラスやLINQを使ってデータベースを操作できます。

EF Coreのメリットは次のとおりです。

  • C#らしいコードでデータベース操作ができる

  • CRUD処理のコード量を減らせる

  • モデルとテーブルの対応を管理しやすい

  • マイグレーションでテーブル変更を管理できる

  • LINQで検索条件を書ける

  • SQL ServerやSQLiteなど複数DBに対応しやすい

特に、Webアプリや業務アプリでは、テーブル数や処理数が増えやすいため、EF Coreを使うことでコードを整理しやすくなります。

7-3. SQLを直接書くべきケース

EF Coreが便利だからといって、すべての場面でSQLを隠すべきとは限りません。

SQLを直接書いた方がよいケースもあります。

たとえば、次のような場合です。

  • 複雑な集計処理を行う

  • パフォーマンスを細かく調整したい

  • 既存のSQL資産を使いたい

  • ストアドプロシージャを呼び出したい

  • EF Coreでは表現しにくいクエリを実行したい

EF CoreでもSQLを直接実行する方法はあります。

C#
var users = context.Users
.FromSqlRaw("SELECT * FROM Users WHERE Name LIKE {0}", "%Taro%")
.ToList();

ただし、SQLを直接実行する場合も、ユーザー入力をそのまま文字列連結しないように注意が必要です。

7-4. 実務で選ばれやすい使い分け

実務では、ADO.NETとEF Coreを目的に応じて使い分けることが多いです。

一般的な目安は次のとおりです。

用途向いている方法
SQLの学習ADO.NET
小規模なCRUDADO.NETまたはEF Core
Webアプリ開発EF Core
業務アプリ開発EF Core
複雑なSQL・高速化ADO.NETまたは生SQL
軽量なローカル保存SQLite
本格的なDB運用SQL Server

初心者は、最初からどれか一つに絞る必要はありません。

まずADO.NETでC#とデータベース接続の基本を理解し、その後EF Coreを学ぶと、実務でも応用しやすくなります。

8. データベース接続でよくあるエラーと対処法

8-1. 接続文字列が間違っている

C#でデータベースに接続できない原因として、接続文字列のミスは非常に多いです。

SQL Serverでは、次のような点を確認しましょう。

  • サーバー名が正しいか

  • データベース名が正しいか

  • 認証方式が正しいか

  • LocalDBが使える状態か

  • \ をC#文字列で正しくエスケープしているか

C#の通常文字列では、\ はエスケープ文字として扱われます。そのため、SQL ServerのLocalDB接続では次のように \\ と書きます。

C#
var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;";

または、逐語的文字列リテラルを使って次のようにも書けます。

C#
var connectionString = @"Server=(localdb)\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;";

SQLiteでは、DBファイルのパスが正しいかを確認しましょう。

C#
var connectionString = "Data Source=sample.db";

相対パスの場合、想定と違うフォルダにDBファイルが作成されていることがあります。

8-2. テーブルやカラムが存在しない

SQLを実行したときに、テーブルやカラムが存在しないというエラーが出ることがあります。

原因としては、次のようなものがあります。

  • テーブルを作成していない

  • テーブル名を間違えている

  • カラム名を間違えている

  • 接続先のデータベースが違う

  • マイグレーションを反映していない

たとえば、SQLでは Users テーブルを参照しているのに、実際には User という名前で作成しているとエラーになります。

SQL
SELECT Id, Name, Email FROM Users;

EF Coreを使っている場合は、マイグレーション後に次のコマンドを実行しているか確認しましょう。

Bash
dotnet ef database update

モデルクラスを作っただけでは、データベースにテーブルは作成されません。

8-3. NuGetパッケージ不足によるエラー

C#でデータベース接続のコードを書いたとき、クラスが見つからないエラーが出ることがあります。

たとえば、次のようなエラーです。

The type or namespace name 'SqlConnection' could not be found

この場合、必要なNuGetパッケージが入っていない可能性があります。

SQL Serverなら、次のパッケージを追加します。

Bash
dotnet add package Microsoft.Data.SqlClient

SQLiteなら、次のパッケージを追加します。

Bash
dotnet add package Microsoft.Data.Sqlite

EF Coreなら、利用するデータベースに応じてパッケージを追加します。

SQLiteの場合です。

Bash
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design

SQL Serverの場合です。

Bash
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design

パッケージを追加したら、using も確認しましょう。

C#
using Microsoft.Data.SqlClient;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

8-4. SQL Serverに接続できない

SQL Serverに接続できない場合は、次の点を確認します。

  • SQL Serverが起動しているか

  • LocalDBがインストールされているか

  • サーバー名が正しいか

  • データベース名が正しいか

  • 認証方式が正しいか

  • ファイアウォールでブロックされていないか

  • 接続先がローカルかリモートか

LocalDBを使う場合、接続文字列は次のようになります。

C#
var connectionString = @"Server=(localdb)\MSSQLLocalDB;Database=SampleDb;Trusted_Connection=True;TrustServerCertificate=True;";

SQL Server認証を使う場合は、ユーザー名とパスワードを指定します。

C#
var connectionString = "Server=localhost;Database=SampleDb;User Id=sa;Password=your_password;TrustServerCertificate=True;";

ただし、パスワードをコードに直接書くのは避けましょう。開発環境では設定ファイルや環境変数を使い、本番環境ではシークレット管理の仕組みを使うのが望ましいです。

8-5. SQLiteのDBファイルが見つからない

SQLiteでよくあるのが、DBファイルの場所が想定と違う問題です。

C#
var connectionString = "Data Source=sample.db";

このように相対パスで指定した場合、sample.db は実行時のカレントディレクトリに作成されます。

プロジェクトフォルダにあると思っていたのに、実際には bin/Debug/netX.X/ 配下に作られていることもあります。

場所を明確にしたい場合は、絶対パスを使います。

C#
var connectionString = @"Data Source=C:\Data\sample.db";

または、アプリケーションの実行フォルダを確認するには次のコードを使います。

C#
Console.WriteLine(AppContext.BaseDirectory);

SQLiteのDBファイルが見つからない場合は、まず実際にどのフォルダで実行されているかを確認しましょう。

9. C#で安全にデータベースを扱うポイント

9-1. usingで接続を確実に閉じる

データベース接続は、使い終わったら閉じる必要があります。

C#では、using を使うことで、処理が終わったときに自動的にリソースを解放できます。

C#
using var connection = new SqliteConnection("Data Source=sample.db");
connection.Open();

// データベース処理

SQL Serverでも同じです。

C#
using var connection = new SqlConnection(connectionString);
connection.Open();

// データベース処理

接続を開きっぱなしにすると、接続数が増えたり、パフォーマンスに影響したりする可能性があります。

データベース接続、コマンド、リーダーなどは、基本的に using を使って確実に破棄しましょう。

9-2. SQLインジェクション対策を行う

SQLインジェクションとは、ユーザー入力を悪用して、意図しないSQLを実行させる攻撃です。

危険な例は次のようなコードです。

C#
var name = Console.ReadLine();

var sql = "SELECT * FROM Users WHERE Name = '" + name + "'";

このように文字列連結でSQLを作ると、悪意のある入力によってSQLの意味が変わる可能性があります。

たとえば、ログイン処理や検索処理でユーザー入力をそのままSQLに連結するのは危険です。

安全にするには、パラメータ化クエリを使います。

9-3. パラメータ化クエリを使う

パラメータ化クエリとは、SQL文に値を直接埋め込まず、パラメータとして渡す方法です。

SQL Serverの例です。

C#
var sql = "SELECT Id, Name, Email FROM Users WHERE Name = @Name";

using var command = new SqlCommand(sql, connection);
command.Parameters.AddWithValue("@Name", name);

SQLiteの例です。

C#
var sql = "SELECT Id, Name, Email FROM Users WHERE Name = @Name";

using var command = new SqliteCommand(sql, connection);
command.Parameters.AddWithValue("@Name", name);

INSERTでも同じです。

C#
var sql = "INSERT INTO Users (Name, Email) VALUES (@Name, @Email)";

using var command = new SqliteCommand(sql, connection);
command.Parameters.AddWithValue("@Name", "Taro");
command.Parameters.AddWithValue("@Email", "taro@example.com");
command.ExecuteNonQuery();

C#でデータベースを安全に扱うなら、ユーザー入力をSQL文字列に直接連結しないことが基本です。

9-4. 例外処理を実装する

データベース処理では、接続エラー、SQLエラー、ファイルエラーなどが発生する可能性があります。

そのため、必要に応じて try-catch を使います。

C#
try
{
using var connection = new SqliteConnection("Data Source=sample.db");
connection.Open();

var sql = "SELECT Id, Name, Email FROM Users";

using var command = new SqliteCommand(sql, connection);
using var reader = command.ExecuteReader();

while (reader.Read())
{
Console.WriteLine($"{reader.GetInt32(0)}: {reader.GetString(1)}");
}
}
catch (Exception ex)
{
Console.WriteLine("データベース処理でエラーが発生しました。");
Console.WriteLine(ex.Message);
}

開発中は ex.Message を表示すると原因を調べやすくなります。

ただし、本番環境ではエラー内容をそのままユーザーに見せないように注意しましょう。接続文字列や内部情報が漏れる可能性があります。

9-5. パスワードや接続情報をコードに直書きしない

接続文字列にユーザー名やパスワードを含める場合、コードに直接書くのは避けましょう。

悪い例です。

C#
var connectionString = "Server=localhost;Database=SampleDb;User Id=sa;Password=password123;";

このように書くと、ソースコードを共有したときにパスワードが漏れる可能性があります。

代わりに、次のような方法を使います。

  • 設定ファイルに分離する

  • 環境変数から読み込む

  • 開発用シークレットを使う

  • 本番環境のシークレット管理サービスを使う

コンソールアプリで環境変数から取得する例です。

C#
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");

if (string.IsNullOrEmpty(connectionString))
{
throw new InvalidOperationException("接続文字列が設定されていません。");
}

データベース接続情報は重要な機密情報です。C#でアプリを作るときは、早い段階から安全な管理方法を意識しましょう。

10. 初心者向けの学習ステップ

10-1. まずはSQLiteでCRUDを試す

C#でデータベースを初めて学ぶなら、まずSQLiteでCRUDを試すのがおすすめです。

SQLiteなら、サーバー設定をほとんど気にせず、1つのDBファイルで学習できます。

最初にやるべきことは、次の4つです。

  • テーブルを作成する

  • INSERTでデータを追加する

  • SELECTでデータを取得する

  • UPDATEとDELETEを試す

この流れを理解できれば、C#からデータベースに接続して操作する基本が身につきます。

初心者は、いきなり大きなアプリを作るよりも、まずコンソールアプリで小さく試す方が理解しやすいです。

10-2. 次にSQL Serverで接続を学ぶ

SQLiteで基本を理解したら、次にSQL Serverを学びましょう。

SQL Serverは、実務でもよく使われる本格的なデータベースです。

学ぶべきポイントは次のとおりです。

  • SQL ServerやLocalDBへの接続

  • 接続文字列の書き方

  • SQL Server用のデータ型

  • SQL Server Management Studioの使い方

  • 認証方式の違い

  • テーブル設計の基本

SQL Serverを使えるようになると、業務アプリやWebアプリの開発に応用しやすくなります。

C#とSQL Serverは相性がよく、.NET環境ではよく使われる組み合わせです。

10-3. EF Coreで効率的な実装を覚える

ADO.NETでSQLの基本を理解したら、EF Coreを学びましょう。

EF Coreを使うと、データベース操作をC#のコードで効率よく書けます。

学習する順番は次のようにするとスムーズです。

  1. モデルクラスを作る

  2. DbContextを作る

  3. マイグレーションを作成する

  4. データベースへ反映する

  5. Addで登録する

  6. LINQで検索する

  7. SaveChangesで更新する

  8. Removeで削除する

EF Coreを使いこなすには、LINQの知識も重要です。

また、EF Coreが裏側でどのようなSQLを発行しているかも意識すると、パフォーマンス面でのトラブルを避けやすくなります。

10-4. Webアプリや業務アプリに応用する

C#でデータベース接続とCRUDが理解できたら、次はWebアプリや業務アプリに応用しましょう。

たとえば、次のようなアプリを作ると実践的な力がつきます。

  • ユーザー管理アプリ

  • 商品管理アプリ

  • タスク管理アプリ

  • 在庫管理アプリ

  • 問い合わせ管理アプリ

  • 売上記録アプリ

ASP.NET CoreとEF Coreを組み合わせれば、Web画面からデータベースを操作するアプリを作れます。

Windowsアプリであれば、WPFやWindows Formsとデータベースを組み合わせることもできます。

最初は小さなCRUDアプリで十分です。登録、一覧表示、編集、削除ができるアプリを作るだけでも、C# データベース開発の基本がかなり身につきます。

まとめ

C#でデータベースを扱うには、まずCRUDの基本を理解することが重要です。

CRUDとは、Create、Read、Update、Deleteの4つの操作であり、データベースを使うほとんどのアプリケーションで必要になります。

C#からデータベースに接続する方法には、SQLを直接実行するADO.NET、軽量なSQLite、本格的なSQL Server、ORMとして使えるEF Coreなどがあります。

初心者におすすめの学習順序は、まずSQLiteでCRUDを試し、次にSQL Serverで接続やSQLの基本を学び、その後EF Coreで効率的な実装を覚える流れです。

ADO.NETはSQLやデータベース接続の仕組みを理解するのに役立ちます。一方、EF CoreはC#のクラスやLINQを使って効率よくデータベース操作ができるため、実務でもよく使われます。

また、C#でデータベースを扱うときは、using で接続を確実に閉じる、SQLインジェクション対策としてパラメータ化クエリを使う、接続文字列やパスワードを安全に管理する、といった点も大切です。

C# データベース開発は、最初は難しく感じるかもしれません。しかし、接続、INSERT、SELECT、UPDATE、DELETEの流れを一つずつ実装していけば、確実に理解できます。

まずはコンソールアプリとSQLiteで小さなCRUD処理を作り、慣れてきたらSQL ServerやEF Core、Webアプリ開発へとステップアップしていきましょう。