【问题标题】:Does Dapper support SQL 2008 Table-Valued Parameters?Dapper 是否支持 SQL 2008 表值参数?
【发布时间】:2011-06-03 21:44:38
【问题描述】:

有谁知道是否可以使用 Dapper 将 table-valued parameter 数据传递给存储过程?

【问题讨论】:

标签: .net dapper


【解决方案1】:

现在(n 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
    }, ...);        
    

其中任何一个都应该可以正常工作。

【讨论】:

  • 我无法使用 Dapper 添加 TVP 的情况,如果我需要添加非输入参数以及使用动态参数,我无法添加 TVP,请检查我的问题@ stackoverflow.com/questions/33087629/…
  • 呸,没有 IEnumerable 转换?
  • 使用ExecuteReader,我得到“System.Data.DataTable 类型的成员事件不能用作参数值”。
【解决方案2】:

是的,我们支持它们,但您需要编写自己的助手代码。

例如:

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 比“where col in @values”要慢。如何使用列表支持功能(Dapper 允许您传入 IEnumerable 并将自动参数化您的查询)将整数列表传递给 StoredProcedure?
  • 这是那些疯狂的边缘情况之一,其中批处理比 sps 更快,dapper 用于列表支持的技术与存储的过程不兼容
  • 你能更新一下吗?我不太清楚在较新版本的 Dapper 中忽略身份参数是否可以。
  • 这段代码是按原样工作还是需要将 IEnumerable 集合转换为 DataTable 以用作 TVP
【解决方案3】:

我知道这张票很旧,很旧,但想让你知道我已经发布了 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 测试项目的原始类。

享受吧!

【讨论】:

  • 我试图了解如何将 TVP 作为参数以及其他典型类型的参数。这是怎么做到的?
  • 我还没有实现那部分。
【解决方案4】:

今天不是。我们实际上为我们厚颜无耻的“in”实现(where col in @values)调查了 table-valed-parameters,但对性能非常不满意。但是在 SPROC 的上下文中它是有意义的。

您最好的选择是log this as an issue on the project site,以便我们对其进行跟踪/优先处理。不过,这听起来像是可行的,可能类似于 DbString 或 DynamicParameters 选项。

但是今天呢?没有。

【讨论】:

  • 更正,我们有点支持它......你只需要自己编码:)
猜你喜欢
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 1970-01-01
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多