Мне нужно было передать целочисленный массив в хранимую процедуру из .NET, и поэтому я искал тему и, в конечном итоге, столкнулся с Arrays and Lists in SQL Server 2008, написанный Эрландом Соммарскогом и предположительно считался стандартным каким образом происходит этот процесс.Тип таблицы SQL Server, определенный пользователем. NET
Я пробовал два разных способа передать определенный пользователем тип таблицы в хранимую процедуру, но я получаю исключения с каждой из них. Оба эти манеры похожи на то, что использует Эрланд Соммарског в приведенной выше ссылке.
Способ # 1 - Использование в качестве DataTable SqlParameter
DataTable dt = new DataTable();
dt.Columns.Add("n", typeof(int));
// Just adding 3 test rows to the DataTable
DataRow dr = dt.NewRow();
dr["n"] = 1;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["n"] = 2;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["n"] = 3;
dt.Rows.Add(dr);
// Creation of the SqlParameter
SqlParameter p = new SqlParameter();
p.ParameterName = "@ids";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "lstInt_TblType";
p.Value = dt;
// Blows up here
DataSet ds = DAWrapper.GetDataSet(
Common.GetDB(),
"usp_Test",
new SqlParameter[] { p });
Исключение, которое я получаю состояния: поток табличных данных (TDS) удаленный вызов процедур (RPC), входящий поток протокола является неправильным. Параметр 1 («@ids»): Тип данных 0x62 (sql_variant) имеет недопустимый тип для метаданных типа.
Способ 2 - Использование списка в качестве SqlParameter
List<SqlDataRecord> lstSDR = new List<SqlDataRecord>();
SqlMetaData[] tvp_definition = { new SqlMetaData("n", SqlDbType.Int) };
// Just adding 3 test rows
SqlDataRecord rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 50);
lstSDR.Add(rec);
rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 51);
lstSDR.Add(rec);
rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 52);
lstSDR.Add(rec);
// Creation of the SqlParameter
SqlParameter p = new SqlParameter();
p.ParameterName = "@ids";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "lstInt_TblType";
p.Value = lstSDR;
// Blows up here
DataSet ds = DAWrapper.GetDataSet(
Common.GetDB(),
"usp_Test",
new SqlParameter[] { p });
И за исключением того, что я получаю за это те, говорится: отображение не существует от типа объекта System.Collections.Generic.List`1 [ [Microsoft.SqlServer.Server.SqlDataRecord, System.Data, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]] к известному встроенному типу управляемого поставщика.
Другая информация lstInt_TblType является определенный пользователем тип Столик в моем SQL Server 2008. Она существует (я трижды проверил это!). Он имеет один столбец с именем «n», типа int, первичный ключ и не допускает нулей. Я точно скопировал, как Эрланд установил его.
Я также подтвердил, что хранимая процедура usp_Test работает из SQL Server Manager Studio, поэтому я вполне уверен, что исключения не выдаются из этого направления. Это T-SQL, которые я использовал, чтобы убедиться, что хранимая процедура работы:
DECLARE @ids lstInt_TblType
INSERT @ids(n) VALUES(1),(2),(3)
EXEC usp_Test ids
Любые предложения о том, куда идти с этим было бы весьма признателен. Благодаря!
* EDIT: * Хранимая процедура usp_Test:
ALTER PROCEDURE [dbo].[usp_Test]
(
@ids lstInt_TblType READONLY
)
AS
BEGIN
SET NOCOUNT ON;
select *
from dbo.dat_MetaData
where MetaDataTypeID in (select n from @ids)
END
GO
Определяется тип таблицы в той же базе данных вы подключаетесь? – Oded
@Oded - Спасибо за вопрос. Я просто дважды проверил, что он попадает в правильную базу данных, и это так. – Jagd
Также стоит проверить имена схем, возможно, добавить имя схемы к типу (то есть 'dbo.tvp_name'). – Oded