C# から SQL Server ストアドプロシージャに List<> を渡す方法
C# から SQL ストアドプロシージャに List<> を渡す方法
Table-Valued Parameter (TVP) を使用する
TVP は、ストアドプロシージャに渡すデータ構造を事前に定義できる機能です。C# の List<>
型と同様の構造を持つ TVP を定義することで、List<>
の内容を効率的にストアドプロシージャに渡すことができます。
TVP を使用する場合のメリット
- データ構造を事前に定義することで、コードの可読性と保守性を向上させることができる
- パラメータのサイズが大きくなっても、効率的にデータを渡すことができる
- 事前に TVP を定義する必要があるため、開発の手間が増える
- 古いバージョンの SQL Server では使用できない
TVP を使用したサンプルコード
// C#
// ストアドプロシージャで使用する TVP の定義
[TableValuedParameter("MyTable")]
public class MyTableType
{
public int Id { get; set; }
public string Name { get; set; }
}
// ストアドプロシージャの呼び出し
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<MyTableType>
{
new MyTableType { Id = 1, Name = "John Doe" },
new MyTableType { Id = 2, Name = "Jane Doe" }
};
var tvpParam = cmd.Parameters.AddWithValue("@MyTable", myTable);
tvpParam.TypeName = "MyTableType";
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE TYPE MyTableType AS TABLE
(
Id INT,
Name VARCHAR(50)
)
CREATE PROCEDURE MyStoredProcedure
(
@MyTable MyTableType READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
SqlParameter は、ストアドプロシージャに個々のパラメータを渡すためのオブジェクトです。List<>
型のデータを SqlParameter に渡すには、AddWithValue
メソッドを使用して、List<>
を IEnumerable 型に変換する必要があります。
SqlParameter を使用する場合のメリット
- TVP を使用するよりも開発の手間が軽い
- データ構造を事前に定義できないため、コードの可読性と保守性が低くなる
- パラメータのサイズが大きくなると、データ転送に時間がかかる
// C#
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<int> { 1, 2, 3 };
var param = cmd.Parameters.AddWithValue("@MyTable", myTable);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "int";
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE PROCEDURE MyStoredProcedure
(
@MyTable INT READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
XML を使用する
List<>
型のデータを XML に変換し、ストアドプロシージャに渡す方法もあります。
- データ構造を事前に定義する必要がない
- コードが複雑になる
- データ転送に時間がかかる
// C#
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<string> { "John Doe", "Jane Doe" };
var xml = new XDocument(
new XElement("MyTable",
myTable.Select(x => new XElement("Item", x))
)
);
var param = cmd.Parameters.AddWithValue("@MyTable", xml.ToString());
param.
C# から SQL ストアドプロシージャに List<> を渡す方法のサンプルコード
Table-Valued Parameter (TVP) を使用する
// C#
// ストアドプロシージャで使用する TVP の定義
[TableValuedParameter("MyTable")]
public class MyTableType
{
public int Id { get; set; }
public string Name { get; set; }
}
// ストアドプロシージャの呼び出し
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<MyTableType>
{
new MyTableType { Id = 1, Name = "John Doe" },
new MyTableType { Id = 2, Name = "Jane Doe" }
};
var tvpParam = cmd.Parameters.AddWithValue("@MyTable", myTable);
tvpParam.TypeName = "MyTableType";
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE TYPE MyTableType AS TABLE
(
Id INT,
Name VARCHAR(50)
)
CREATE PROCEDURE MyStoredProcedure
(
@MyTable MyTableType READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
SqlParameter を使用する
// C#
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<int> { 1, 2, 3 };
var param = cmd.Parameters.AddWithValue("@MyTable", myTable);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "int";
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE PROCEDURE MyStoredProcedure
(
@MyTable INT READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
XML を使用する
// C#
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<string> { "John Doe", "Jane Doe" };
var xml = new XDocument(
new XElement("MyTable",
myTable.Select(x => new XElement("Item", x))
)
);
var param = cmd.Parameters.AddWithValue("@MyTable", xml.ToString());
param.SqlDbType = SqlDbType.Xml;
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE PROCEDURE MyStoredProcedure
(
@MyTable XML READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
データテーブルを使用する
// C#
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new DataTable();
myTable.Columns.Add("Id", typeof(int));
myTable.Columns.Add("Name", typeof(string));
foreach (var item in myTable)
{
myTable.Rows.Add(item.Id, item.Name);
}
var param = cmd.Parameters.AddWithValue("@MyTable", myTable);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "MyTableType";
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE TYPE MyTableType AS TABLE
(
Id INT,
Name VARCHAR(50)
)
CREATE PROCEDURE MyStoredProcedure
(
@MyTable MyTableType READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
JSON を使用する
JSON は、データ構造を記述するための軽量なフォーマットです。List<>
型のデータを JSON に変換し、ストアドプロシージャに渡すことができます。
// C#
using (var connection = new SqlConnection("connection string"))
{
var cmd = new SqlCommand("MyStoredProcedure", connection);
cmd.CommandType = CommandType.StoredProcedure;
var myTable = new List<string> { "John Doe", "Jane Doe" };
var json = JsonConvert.SerializeObject(myTable);
var param = cmd.Parameters.AddWithValue("@MyTable", json);
param.SqlDbType = SqlDbType.NVarChar;
cmd.ExecuteNonQuery();
}
// SQL Server
CREATE PROCEDURE MyStoredProcedure
(
@MyTable NVARCHAR(MAX) READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
Dapper を使用する
Dapper は、C# と SQL Server 間のデータアクセスを簡略化するオープンソースのライブラリです。Dapper を使用すると、List<>
型のデータを簡単にストアドプロシージャに渡すことができます。
- パフォーマンスが向上する
- Dapper の使い方を習得する必要がある
// C#
using (var connection = new SqlConnection("connection string"))
{
var myTable = new List<string> { "John Doe", "Jane Doe" };
var result = connection.Query<int>("MyStoredProcedure", new { MyTable = myTable });
}
// SQL Server
CREATE PROCEDURE MyStoredProcedure
(
@MyTable NVARCHAR(MAX) READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
Entity Framework は、C# と SQL Server 間のオブジェクト関係マッピング (ORM) を提供するオープンソースのフレームワークです。Entity Framework を使用すると、List<>
型のデータを簡単にストアドプロシージャに渡すことができます。
- オブジェクト指向の開発が可能になる
- Entity Framework の使い方を習得する必要がある
// C#
using (var context = new MyContext())
{
var myTable = new List<string> { "John Doe", "Jane Doe" };
var result = context.Database.SqlQuery<int>("MyStoredProcedure", new SqlParameter("@MyTable", myTable));
}
// SQL Server
CREATE PROCEDURE MyStoredProcedure
(
@MyTable NVARCHAR(MAX) READONLY
)
AS
BEGIN
-- MyTable の内容を処理
END
上記は、C# から SQL Server ストアドプロシージャに List<> を渡すその他の方法のサンプルコードです。どの方法を使用するかは、状況によって異なります。
c# sql sql-server