Dapper是否支持SQL 2008表值参数?

Car*_*des 75 .net dapper

有谁知道是否可以使用Dapper 将表值参数数据传递给存储过程?

Mar*_*ell 89

现在(n Dapper 1.26和更高版本)直接支持烘焙到精巧的表值参数.对于存储过程,由于数据类型内置于sproc API中,因此您需要做的就是提供DataTable:

var data = connection.Query<SomeType>(..., new {
    id=123, name="abc", values = someTable
}, ...);
Run Code Online (Sandbox Code Playgroud)

对于直接命令文本,您还有两个选项:

  • 使用辅助方法告诉它自定义数据类型:

    var data = connection.Query<SomeType>(..., new {
        id=123, name="abc", values = someTable.AsTableValuedParameter("mytype")
    }, ...);
    
    Run Code Online (Sandbox Code Playgroud)
  • 告诉data-table本身要使用的自定义数据类型:

    someTable.SetTypeName("mytype");
    var data = connection.Query<SomeType>(..., new {
        id=123, name="abc", values = someTable
    }, ...);        
    
    Run Code Online (Sandbox Code Playgroud)

任何这些应该工作正常.

  • 呸,没有IEnumerable转换? (8认同)

Sam*_*ron 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");

    }
}
Run Code Online (Sandbox Code Playgroud)

确保正确测试表值参数的性能.当我测试这个以传递int列表时,它明显慢于传递多个参数.

我完全不反对在contrib项目中为dapper提供一些特定于SQL Server的帮助程序,但是核心的小巧精确可以避免在可能的情况下添加特定于供应商的技巧.


Dar*_*rek 8

我知道这张票是旧的,很老,但是想让你知道我已经发布了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();
Run Code Online (Sandbox Code Playgroud)

它基于Dapper测试项目的原始类.

请享用!


Mar*_*ell 5

今天不是.我们实际上为我们厚颜无耻的"in"实现(where col in @values)调查了table-valed-parameters ,但是对性能却非常不满意.然而,在SPROC的背景下,它是有道理的.

您最好的选择是将此问题记录在项目网站上,以便我们跟踪/确定其优先级.但是,这听起来像是可行的,可能类似于DbString或DynamicParameters选项.

但今天?没有.

  • 纠正,我们支持它...你只需要自己编码:) (2认同)