テーブル値のパラメータデータをDapperを使用してストアドプロシージャに渡すことができるかどうかを誰かが知っていますか?
4 に答える
現在(n Dapper 1.26以降)、dapperにベイクされたテーブル値パラメーターが直接サポートされています。ストアドプロシージャの場合、データ型はsproc APIに組み込まれているため、必要なのはDataTable
:を指定することだけです。
var data = connection.Query<SomeType>(..., new {
id=123, name="abc", values = someTable
}, ...);
直接コマンドテキストの場合、他に2つのオプションがあります。
ヘルパーメソッドを使用して、カスタムデータ型を通知します。
var data = connection.Query<SomeType>(..., new { id=123, name="abc", values = someTable.AsTableValuedParameter("mytype") }, ...);
使用するカスタムデータ型をデータテーブル自体に指示します。
someTable.SetTypeName("mytype"); var data = connection.Query<SomeType>(..., new { id=123, name="abc", values = someTable }, ...);
これらのいずれも正常に動作するはずです。
はい、サポートしていますが、独自のヘルパーをコーディングする必要があります。
例えば:
class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters
{
IEnumerable<int> numbers;
public IntDynamicParam(IEnumerable<int> numbers)
{
this.numbers = numbers;
}
public void AddParameters(IDbCommand command)
{
var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure;
List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();
// Create an SqlMetaData object that describes our table type.
Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };
foreach (int n in numbers)
{
// Create a new record, using the metadata array above.
Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
rec.SetInt32(0, n); // Set the value.
number_list.Add(rec); // Add it to the list.
}
// Add the table parameter.
var p = sqlCommand.Parameters.Add("@ints", SqlDbType.Structured);
p.Direction = ParameterDirection.Input;
p.TypeName = "int_list_type";
p.Value = number_list;
}
}
// SQL Server specific test to demonstrate TVP
public void TestTVP()
{
try
{
connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
connection.Execute("CREATE PROC get_ints @ints int_list_type READONLY AS select * from @ints");
var nums = connection.Query<int>("get_ints", new IntDynamicParam(new int[] { 1, 2, 3 })).ToList();
nums[0].IsEqualTo(1);
nums[1].IsEqualTo(2);
nums[2].IsEqualTo(3);
nums.Count.IsEqualTo(3);
connection.Execute("DROP PROC get_ints");
connection.Execute("DROP TYPE int_list_type");
}
}
テーブル値パラメーターのパフォーマンスを適切にテストするようにしてください。これをintリストの受け渡しについてテストしたところ、複数のパラメーターを渡すよりも大幅に遅くなりました。
私は、contribプロジェクトにdapper用のSQL Server固有のヘルパーを含めることにまったく反対していませんが、コアdapperは、可能な場合はベンダー固有のトリックを追加することを避けています。
このチケットは古く、非常に古いことは知っていますが、一般的なTVPをサポートするDapper.Microsoft.Sqlパッケージを公開したことをお知らせします。
https://www.nuget.org/packages/Dapper.Microsoft.Sql/
使用例:
List<char> nums = this.connection.Query<char>(
"get_ints",
new TableValuedParameter<char>(
"@ints", "int_list_Type", new[] { 'A', 'B', 'C' })).ToList();
これは、Dapperテストプロジェクトの元のクラスに基づいています。
楽しみ!
今日はそうではありません。生意気な「in」実装()のtable-valed-parametersを実際に調査しましwhere col in @values
たが、パフォーマンスにはあまり感心しませんでした。ただし、SPROCのコンテキストでは、それは理にかなっています。
最善の策は、これをプロジェクトサイトに問題として記録して、追跡/優先順位付けできるようにすることです。おそらくDbStringまたはDynamicParametersオプションに似ていますが、何かが実行可能になるようです。
でも今日は?いいえ。