2011-08-08 50 views
29

Tôi đang cố gắng chuyển một tham số giá trị bảng tới một thủ tục được lưu trữ, nhưng tôi vẫn nhận được một ngoại lệ (xem bên dưới).Cách chuyển thông số giá trị bảng

SqlCommand c = new SqlCommand("getPermittedUsers", myConn) { CommandType = CommandType.StoredProcedure }; 

c.Parameters.AddWithValue("@intNotifyingUserId", notifyingUserId); 
c.Parameters.AddWithValue("@tSelectedPdfIds", sharedPdfs).SqlDbType = SqlDbType.Structured; 

SqlDataReader dr = c.ExecuteReader();

Các loại được xác định trên máy chủ như thế này:

CREATE TYPE [dbo].[IdList] AS TABLE(
    [Id] [int] NOT NULL 
)

Tôi đã thử đi qua sharedPdfs như một List<int>, và IQueryable<int>, nhưng tiếp tục nhận được ngoại lệ sau đây:

Object must implement IConvertible.

Bất cứ ai biết tôi đang làm gì sai? Tài liệu ngụ ý rằng tôi có thể chuyển danh sách thành TVP nhưng không đưa ra bất kỳ ví dụ nào.

Cảm ơn bạn.

+0

như thế nào 'getPermittedUsers' tuyên bố? –

+0

Đây là một cảnh quay dài, nhưng bạn đã thử truyền một 'int []'? –

+4

Bạn cần sử dụng 'DataTable'. – ChaosPandion

Trả lời

12

Bạn có thể chuyển tham số dưới dạng DataTable, IEnumerable<SqlDataRecord> hoặc DbDataReader.

+0

? với SQLCommand Bạn có chắc chắn? –

+1

Có, đó là các loại được hỗ trợ cho Tham số giá trị bảng trong SqlCommand. Tài liệu đầy đủ có tại đây: http://msdn.microsoft.com/en-us/library/bb675163.aspx. Xem 1/3 đường xuống: "System.Data.SqlClient hỗ trợ điền các tham số có giá trị bảng từ DataTable, DbDataReader hoặc System.Collections.Generic.IEnumerable ([T: System.Collections.Generic.IEnumerable' 1)] đối tượng. " –

+1

là điều này cũng có thể trong Oracle? –

42

Ví dụ sau minh họa bằng cách sử dụng một DataTable hoặc một IEnumerable<SqlDataRecord>:

SQL Mã

CREATE TABLE dbo.PageView 
(
    PageViewID BIGINT NOT NULL CONSTRAINT pkPageView PRIMARY KEY CLUSTERED, 
    PageViewCount BIGINT NOT NULL 
); 
CREATE TYPE dbo.PageViewTableType AS TABLE 
(
    PageViewID BIGINT NOT NULL 
); 
CREATE PROCEDURE dbo.procMergePageView 
    @Display dbo.PageViewTableType READONLY 
AS 
BEGIN 
    MERGE INTO dbo.PageView AS T 
    USING @Display AS S 
    ON T.PageViewID = S.PageViewID 
    WHEN MATCHED THEN UPDATE SET T.PageViewCount = T.PageViewCount + 1 
    WHEN NOT MATCHED THEN INSERT VALUES(S.PageViewID, 1); 
END 

C# Mã

private static void ExecuteProcedure(bool useDataTable, string connectionString, IEnumerable<long> ids) { 
    using (SqlConnection connection = new SqlConnection(connectionString)) { 
     connection.Open(); 
     using (SqlCommand command = connection.CreateCommand()) { 
      command.CommandText = "dbo.procMergePageView"; 
      command.CommandType = CommandType.StoredProcedure; 

      SqlParameter parameter; 
      if (useDataTable) { 
       parameter = command.Parameters.AddWithValue("@Display", CreateDataTable(ids)); 
      } 
      else { 
       parameter = command.Parameters.AddWithValue("@Display", CreateSqlDataRecords(ids)); 
      } 
      parameter.SqlDbType = SqlDbType.Structured; 
      parameter.TypeName = "dbo.PageViewTableType"; 

      command.ExecuteNonQuery(); 
     } 
    } 
} 

private static DataTable CreateDataTable(IEnumerable<long> ids) { 
    DataTable table = new DataTable(); 
    table.Columns.Add("ID", typeof(long)); 
    foreach (long id in ids) { 
     table.Rows.Add(id); 
    } 
    return table; 
} 

private static IEnumerable<SqlDataRecord> CreateSqlDataRecords(IEnumerable<long> ids) { 
    SqlMetaData[] metaData = new SqlMetaData[1]; 
    metaData[0] = new SqlMetaData("ID", SqlDbType.BigInt); 
    SqlDataRecord record = new SqlDataRecord(metaData); 
    foreach (long id in ids) { 
     record.SetInt64(0, id); 
     yield return record; 
    } 
} 
+1

Điều này đã giúp tôi, cảm ơn! – s0nica

+0

đã cố gắng để có được tvp làm việc từ những gì tôi tìm thấy trên http://sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql, nhưng tiếp tục nhận được giá trị dbnull. Ví dụ của bạn đã kết thúc làm việc cho tôi, có thể là parameter.typename. Cảm ơn! – Phil

+0

NB: Đối với những người không muốn tạo loại tùy chỉnh cho điều này, giải pháp thay thế là chuyển dữ liệu dưới dạng loại xml, sau đó truy vấn dựa vào đó. – JohnLBevan

Các vấn đề liên quan