テーブル値パラメーターをストアドプロシージャに渡そうとしていますが、例外が発生し続けます(以下を参照)。
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();
タイプは次のようにサーバー上で定義されます。
CREATE TYPE [dbo].[IdList] AS TABLE(
[Id] [int] NOT NULL
)
SharedPdfsをList<int>
およびIQueryable<int>
として渡そうとしましたが、次の例外が発生し続けます。
Object must implement IConvertible.
誰が私が間違っているのか知っていますか?このドキュメントは、リストをTVPとして渡すことができるはずであることを暗示していますが、例を挙げていません。
ありがとうございました。
パラメーターは、DataTable
、IEnumerable<SqlDataRecord>
、またはDbDataReader
として渡すことができます。
次の例は、DataTable
またはIEnumerable<SqlDataRecord>
の使用を示しています。
SQLコード
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#コード
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;
}
}