2011-06-03 17 views

回答

78

现在(n Dapper 1.26和更高版本)直接支持表格参数烘焙到短小精悍。在存储过程的情况下,由于数据类型内置存储过程的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 
    }, ...);   
    

所有的这些都应该很好地工作。

+0

如果我无法使用Dapper添加TVP,如果我需要非输入参数以及使用Dynamic Parameters,我无法添加TVP,请检查我的问题@ http:// stackoverflow .com/questions/33087629/dapper-dynamic-parameters-with-table-valued -value参数 – 2015-10-15 07:28:06

+7

Bah,没有IEnumerable转换? – Nuzzolilo 2015-10-24 01:40:18

+0

使用'ExecuteReader',我得到“System.Data.DataTable类型的成员事件不能用作参数值”。 – 2018-03-07 19:25:34

5

今天它不是。我们实际上调查了我们厚颜无耻的“in”实现(where col in @values)中的table-valed-参数,但对性能非常不感兴趣。然而,在SPROC的情况下,这是有道理的。

你最好打的是log this as an issue on the project site,所以我们可以跟踪/优先化它。这听起来像是可行的,但可能类似于DbString或DynamicParameters选项。

但今天?号码

+2

更正,我们有点支持它......你只需要自己编码:) – 2011-06-06 00:33:32

27

是的,我们支持他们,但你需要编写你自己的助手。

例如:

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"); 

    } 
} 

确保正确测试表值PARAMS性能。当我测试这个传递int列表时,它显着比传入多个参数慢。

我完全不反对在contrib项目中使用一些SQL Server特定的辅助工具,但是核心工具可以避免在可能的情况下添加供应商特定的技巧。

+1

事实上,使用TVP比“哪里有@values”慢。如何使用列表支持功能(Dapper允许您传入IEnumerable 并自动参数化您的查询)以将整数列表传递给StoredProcedure? – 2011-07-06 16:28:51

+0

这是批处理比sps更快的疯狂边缘情况之一快速清单技术用于列表支持的技术与存储的procs不兼容 – 2011-07-06 21:49:31

+0

你能否更新?我无法弄清楚在较新版本的Dapper中忽略身份参数是否可行。 – Crisfole 2014-07-07 14:17:50

7

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

它是在原有基础上,从类小巧玲珑的测试项目。

享受!

+0

我想了解如何将TVP作为参数以及其他典型类型的参数。这是如何完成的? – Snowy 2014-02-28 15:22:11

+0

我还没有实现那个部分。 – Darek 2014-03-02 17:03:42