有谁知道是否可以使用Dapper将表值参数数据传递到存储过程?
Answers:
现在(对Dapper 1.26或更高版本)直接支持烘焙到dapper中的表值参数。对于存储过程,由于数据类型内置在sproc API中,因此您需要做的就是提供DataTable
:
var data = connection.Query<SomeType>(..., new {
id=123, name="abc", values = someTable
}, ...);
对于直接命令文本,您还有两个选择:
使用辅助方法告诉它自定义数据类型:
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
}, ...);
这些中的任何一个都可以正常工作。
ExecuteReader
,我得到“ System.Data.DataTable类型的成员事件不能用作参数值”。
是的,我们支持他们,但是您将需要编写自己的助手。
例如:
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项目中使用一些SQL Server专用的dapper帮助程序,但是核心dapper避免在可能的地方添加特定于供应商的技巧。
我知道这张票是旧的,很旧,但是想让您知道我已经发布了Dapper.Microsoft.Sql程序包,该程序包支持通用TVP。
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测试项目中的原始类。
请享用!
今天不是。实际上,我们调查了表值参数以实现我们的厚颜无耻的“实现”(where col in @values
),但对性能没有任何印象。但是,在SPROC的上下文中,这是有道理的。
最好的选择是将此问题记录在项目站点上,以便我们跟踪/确定其优先级。听起来有些事情是可行的,但可能类似于DbString或DynamicParameters选项。
但今天?没有。