2011-06-03 38 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