2012-05-16 3 views
4

Мне нужно было передать целочисленный массив в хранимую процедуру из .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 
+0

Определяется тип таблицы в той же базе данных вы подключаетесь? – Oded

+0

@Oded - Спасибо за вопрос. Я просто дважды проверил, что он попадает в правильную базу данных, и это так. – Jagd

+0

Также стоит проверить имена схем, возможно, добавить имя схемы к типу (то есть 'dbo.tvp_name'). – Oded

ответ

2

Нашли другой способ идти о делать это. Этот способ использует библиотеки System.Data.SqlClient для создания соединения с базой данных, указания имени хранимой процедуры и затем передачи параметра в виде DataTable, который используется в качестве типа таблицы SQL Server, определяемой пользователем.

using (SqlConnection conn = new SqlConnection(connStr)) { 
    SqlCommand cmd = conn.CreateCommand(); 
    cmd.CommandType = System.Data.CommandType.StoredProcedure; 
    cmd.CommandText = "dbo.usp_Test"; 
    cmd.Parameters.AddWithValue("@ids", dt); 
    conn.Open(); 

    using (SqlDataReader sqlReader = cmd.ExecuteReader()) { 
     DataTable retTbl = new DataTable(); 
     retTbl.Load(sqlReader); 
    } 
} 
Смежные вопросы