C#、SQL Server、T-SQL を使ったストアドプロシージャ開発のベストプラクティス
C#、SQL Server、T-SQL を使って配列を SQL Server ストアド プロシージャに渡す方法
前提条件
- Visual Studio 2019 または 2022
- SQL Server Management Studio (SSMS)
- SQL Server データベース
手順
-
C# プロジェクトの作成
-
NuGet パッケージの追加
ソリューション エクスプローラーでプロジェクトを右クリックし、NuGet パッケージの管理 を選択します。NuGet パッケージ マネージャー で、以下のパッケージを検索してインストールします。
System.Data.SqlClient
Microsoft.Extensions.Configuration
-
App.config ファイルの編集
<configuration>
<connectionStrings>
<add name="MyConnectionString" connectionString="Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True;" />
</connectionStrings>
</configuration>
-
ストアド プロシージャの作成
CREATE PROCEDURE [dbo].[GetNames]
@names VARCHAR(MAX)
AS
BEGIN
SELECT Name
FROM dbo.People
WHERE Name IN (SELECT Value FROM dbo.SplitString(@names, ','))
END
-
C# コードの作成
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
// 配列を初期化します
string[] names = new string[] { "John", "Jane", "Michael" };
// 接続文字列を取得します
string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
// SqlConnection オブジェクトを作成します
using (SqlConnection connection = new SqlConnection(connectionString))
{
// SqlCommand オブジェクトを作成します
using (SqlCommand command = new SqlCommand("dbo.GetNames", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
// パラメータを追加します
command.Parameters.AddWithValue("@names", string.Join(",", names));
// SqlCommand を実行します
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// 結果を読み取ります
while (reader.Read())
{
Console.WriteLine(reader["Name"]);
}
}
}
}
}
}
-
コードの実行
John
Jane
Michael
説明
このコードでは、以下の方法で配列を SQL Server ストアド プロシージャに渡しています。
- C# コードで配列を初期化します。
SqlCommand
オブジェクトを作成し、ストアド プロシージャの名前を指定します。AddWithValue
メソッドを使って、ストアド プロシージャのパラメータに配列を渡します。SqlCommand
オブジェクトを実行します。
- SQL Server には、テーブル値パラメータと呼ばれる、ストアド プロシージャに配列を渡す別の方法もあります。
// C# コード
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
// 配列を初期化します
string[] names = new string[] { "John", "Jane", "Michael" };
// 接続文字列を取得します
string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
// SqlConnection オブジェクトを作成します
using (SqlConnection connection = new SqlConnection(connectionString))
{
// SqlCommand オブジェクトを作成します
using (SqlCommand command = new SqlCommand("dbo.GetNames", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
// パラメータを追加します
command.Parameters.AddWithValue("@names", string.Join(",", names));
// SqlCommand を実行します
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// 結果を読み取ります
while (reader.Read())
{
Console.WriteLine(reader["Name"]);
}
}
}
}
}
}
// SQL Server ストアド プロシージャ
CREATE PROCEDURE [dbo].[GetNames]
@names VARCHAR(MAX)
AS
BEGIN
SELECT Name
FROM dbo.People
WHERE Name IN (SELECT Value FROM dbo.SplitString(@names, ','))
END
// App.config ファイル
<configuration>
<connectionStrings>
<add name="MyConnectionString" connectionString="Data Source=localhost;Initial Catalog=MyDatabase;Integrated Security=True;" />
</connectionStrings>
</configuration>
John
Jane
Michael
このサンプルコードは、C#、SQL Server、T-SQL を使って配列を SQL Server ストアド プロシージャに渡す方法を示しています。
SQL Server ストアド プロシージャに配列を渡す他の方法
XML を使う方法
配列を XML に変換し、ストアド プロシージャのパラメータとして渡すことができます。
// 配列を XML に変換します
string xml = string.Join(",", names.Select(x => $"<value>{x}</value>"));
// SqlCommand オブジェクトを作成します
using (SqlCommand command = new SqlCommand("dbo.GetNames", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
// パラメータを追加します
command.Parameters.AddWithValue("@names", xml);
// SqlCommand を実行します
...
}
SQL Server ストアド プロシージャ
CREATE PROCEDURE [dbo].[GetNames]
@names XML
AS
BEGIN
SELECT Name
FROM dbo.People
WHERE Name IN (SELECT value FROM @names.nodes('/values/value'))
END
テーブル変数を使う方法
一時テーブルを作成し、配列のデータを挿入してから、ストアド プロシージャのパラメータとして渡すことができます。
// テーブル変数を作成します
using (SqlCommand command = new SqlCommand("CREATE TABLE #Names (Name VARCHAR(MAX))", connection))
{
command.ExecuteNonQuery();
}
// 配列のデータを挿入します
foreach (string name in names)
{
using (SqlCommand command = new SqlCommand("INSERT INTO #Names (Name) VALUES (@name)", connection))
{
command.Parameters.AddWithValue("@name", name);
command.ExecuteNonQuery();
}
}
// SqlCommand オブジェクトを作成します
using (SqlCommand command = new SqlCommand("dbo.GetNames", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
// パラメータを追加します
command.Parameters.AddWithValue("@names", "#Names");
// SqlCommand を実行します
...
}
CREATE PROCEDURE [dbo].[GetNames]
@names VARCHAR(MAX)
AS
BEGIN
SELECT Name
FROM dbo.People
WHERE Name IN (SELECT Name FROM @names)
END
分割して渡す方法
// 配列を分割します
int chunkSize = 100;
for (int i = 0; i < names.Length; i += chunkSize)
{
// パラメータを追加します
command.Parameters.AddWithValue("@names" + i, string.Join(",", names.Skip(i).Take(chunkSize)));
// SqlCommand を実行します
...
}
CREATE PROCEDURE [dbo].[GetNames]
@names1 VARCHAR(MAX),
@names2 VARCHAR(MAX),
...
AS
BEGIN
SELECT Name
FROM dbo.People
WHERE Name IN (@names1, @names2, ...)
END
これらの方法にはそれぞれメリットとデメリットがあります。どの方法を使うかは、状況によって異なります。
C#、SQL Server、T-SQL を使って配列を SQL Server ストアド プロシージャに渡す方法はいくつかあります。どの方法を使うかは、状況によって異なります。
c# sql-server t-sql