是否有人知道是否可以使用Dapper将table-valued parameter数据传递给存储过程?
答案 0 :(得分:85)
现在(n Dapper 1.26及更高版本)直接支持烘焙到精巧的表值参数。对于存储过程,由于数据类型内置于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
}, ...);
任何这些都应该可以正常工作。
答案 1 :(得分:28)
是的,我们支持他们,但您需要编写自己的助手。
例如:
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特定的帮助程序,但是核心的小工具避免在可能的情况下添加特定于供应商的技巧。
答案 2 :(得分:8)
我知道这张票是OLD,很旧,但是想告诉你我已经发布了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测试项目的原始类。
享受!
答案 3 :(得分:5)
今天它不是。我们实际上为我们的厚脸皮&#34;在&#34;中调查了表格式参数。实现(where col in @values
),但对性能非常不满意。然而,在SPROC的背景下,它是有道理的。
您最好的选择是log this as an issue on the project site,以便我们跟踪/优先排序。听起来有点可行,可能类似于DbString或DynamicParameters选项。
但今天呢?否。