C# でできる SQL Server テーブル変更監視:サンプルコード付きでわかりやすく解説
C# で SQL Server テーブル変更を監視する方法
変更データ キャプチャ (CDC)
CDC は、SQL Server に組み込まれた機能で、データベース内のデータ変更を追跡する最も効率的な方法の 1 つです。 CDC を使用すると、挿入、更新、削除などの操作に関する情報を取得できます。
CDC を C# で使用するには、次の手順に従います。
.NET Framework Data Provider for SQL Server
NuGet パッケージをプロジェクトにインストールします。System.Data.SqlClient
名前空間を using ディレクティブに追加します。SqlConnection
オブジェクトを作成し、SQL Server インスタンスに接続します。SqlCommand
オブジェクトを作成し、CDC を有効にする T-SQL コマンドを実行します。SqlNotificationRequest
オブジェクトを作成し、監視するテーブルと列を指定します。SqlNotificationService
オブジェクトを作成し、SqlNotificationRequest
オブジェクトを渡します。SqlNotificationService.Start()
メソッドを呼び出して、通知の監視を開始します。SqlNotificationEventHandler
делегатを作成し、データ変更イベントが発生したときに呼び出されるようにします。SqlNotificationService.Subscribe()
メソッドを使用して、SqlNotificationEventHandler
делеゲートをSqlNotificationService
オブジェクトに登録します。
トリガー
トリガーは、データベース内のデータが変更されたときに自動的に実行されるストアド プロシージャです。 トリガーを使用して、C# アプリケーションに通知を送信したり、他のアクションを実行したりできます。
トリガーを使用して C# で SQL Server テーブル変更を監視するには、次の手順に従います。
- 監視するテーブルに対して INSERT、UPDATE、または DELETE トリガーを作成します。
- トリガー内で、C# アプリケーションに通知を送信するコードを追加します。
ポーリング
ポーリングは、一定間隔で SQL Server テーブルをクエリして、変更がないかどうかを確認する最も単純な方法です。 ポーリングは、他の方法と比較してパフォーマンスが低くなりますが、実装が最も簡単です。
- 監視するテーブルに対してクエリを作成します。
Timer
クラスを使用して、クエリを一定間隔で実行します。- クエリの結果を前回のクエリ結果と比較して、変更がないかどうかを確認します。
- 変更がある場合は、必要な処理を実行します。
どの方法を選択するべきですか?
使用する方法は、要件によって異なります。
- パフォーマンスが重要ではない場合 は、ポーリングを使用するのが最善の方法です。
- 特定の操作に対してのみアクションを実行する必要がある場合 は、トリガーを使用するのが最善の方法です。
- 変更を追跡する必要がある場合 は、CDC を使用するのが最善の方法です。
using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.ChangeData.DataAccess;
namespace SqlServerCdcSample
{
class Program
{
static void Main(string[] args)
{
// 接続文字列を指定
string connectionString = "Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True";
// 監視するテーブルと列を指定
string tableName = "MyTable";
string[] columnNames = new string[] { "Id", "Name", "Price" };
// CDC サービスを作成
using (var cdcService = new ChangeDataCaptureService(connectionString))
{
// データ変更イベントが発生したときの処理を定義
cdcService.OnChangeEvent += OnChangeEvent;
// CDC サービスを開始
cdcService.Start();
// コンソールに入力があるまで待機
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
// CDC サービスを停止
cdcService.Stop();
}
}
static void OnChangeEvent(object sender, ChangeDataEventArgs e)
{
// 変更されたデータを取得
var changeTable = e.ChangeTable;
// 変更された各行を処理
foreach (DataRow row in changeTable.Rows)
{
// 変更の種類を取得
ChangeType changeType = row.RowState;
// 変更された列を取得
var changedColumns = row.GetModifiedColumns();
// 変更された値を取得
foreach (DataColumn column in changedColumns)
{
object newValue = row[column];
// 変更内容をコンソールに出力
Console.WriteLine($"Table: {tableName}, ChangeType: {changeType}, Column: {column.ColumnName}, NewValue: {newValue}");
}
}
}
}
}
using System;
using System.Data.SqlClient;
namespace SqlServerTriggerSample
{
class Program
{
static void Main(string[] args)
{
// 接続文字列を指定
string connectionString = "Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True";
// トリガーを作成
string triggerSql = @"
CREATE TRIGGER MyTrigger ON MyTable
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
-- C# アプリケーションに通知を送信
-- 例: 電子メールを送信
-- ...
END
";
// トリガーを作成する
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var command = new SqlCommand(triggerSql, connection))
{
command.ExecuteNonQuery();
}
}
// コンソールに入力があるまで待機
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
using System;
using System.Data.SqlClient;
namespace SqlServerPollingSample
{
class Program
{
static void Main(string[] args)
{
// 接続文字列を指定
string connectionString = "Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True";
// 監視するテーブルと列を指定
string tableName = "MyTable";
string[] columnNames = new string[] { "Id", "Name", "Price" };
// 前回のクエリ結果を格納する変数
DataRow previousRow = null;
// ポーリング間隔を指定 (ミリ秒)
int pollingInterval = 10000;
while (true)
{
// クエリを実行
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var command = new SqlCommand($"SELECT {string.Join(",", columnNames)} FROM {tableName}", connection))
{
var reader = command.ExecuteReader();
if (reader.Read())
{
// 現在のクエリ結果を取得
DataRow currentRow = reader[0];
// 前回のクエリ結果と比較
if (previousRow != null)
{
// 変更がある場合は処理を実行
foreach (DataColumn column in columnNames)
{
カスタム ソリューション
ログの監視
サードパーティ製のツール
- 高いセキュリティが必要な場合 は、ログの監視を使用するのが最善の方法です。
- 複雑な監視シナリオが必要な場合 は、サードパーティ製のツールを使用するか、カスタム ソリューションを開発するのが最善の方法です。
- シンプルな監視ソリューションが必要な場合 は、変更データ キャプチャ (CDC) を使用するのが最善の方法です。
c# sql-server monitoring