Cómo pasar parámetros de valores de tabla al procedimiento almacenado desde código .net

Resuelto Marek Kwiendacz asked hace 13 años • 0 respuestas

Tengo una base de datos SQL Server 2005. En algunos procedimientos tengo parámetros de tabla que paso a un proceso almacenado como nvarchar(separados por comas) y los divido internamente en valores únicos. Lo agrego a la lista de parámetros del comando SQL así:

cmd.Parameters.Add("@Logins", SqlDbType.NVarchar).Value = "jim18,jenny1975,cosmo";

Tengo que migrar la base de datos a SQL Server 2008. Sé que existen parámetros de valores de tabla y sé cómo usarlos en procedimientos almacenados. Pero no sé cómo pasar uno a la lista de parámetros en un comando SQL.

¿Alguien conoce la sintaxis correcta del Parameters.Addprocedimiento? ¿O hay otra forma de pasar este parámetro?

Marek Kwiendacz avatar Apr 08 '11 19:04 Marek Kwiendacz
Aceptado

DataTableSe pueden utilizar objetos DbDataReader, u objetos para completar un parámetro con valores de tabla según el artículo de MSDN Parámetros con valores de tabla en SQL Server 2008 (ADO.NET) .IEnumerable<SqlDataRecord>

El siguiente ejemplo ilustra el uso de a DataTableo an IEnumerable<SqlDataRecord>:

Código 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ódigo 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;
    }
}
Ryan Prechel avatar May 28 '2012 05:05 Ryan Prechel

Además de la respuesta de Ryan, también deberá establecer la DataColumnpropiedad Ordinalsi se trata de un table-valued parametercon varias columnas cuyos ordinales no están en orden alfabético.

Como ejemplo, si tiene el siguiente valor de tabla que se utiliza como parámetro en SQL:

CREATE TYPE NodeFilter AS TABLE (
  ID int not null
  Code nvarchar(10) not null,
);

Necesitaría ordenar sus columnas como tales en C#:

table.Columns["ID"].SetOrdinal(0);
// this also bumps Code to ordinal of 1
// if you have more than 2 cols then you would need to set more ordinals

Si no hace esto, obtendrá un error de análisis, no se pudo convertir nvarchar a int.

Scotty.NET avatar Nov 26 '2013 15:11 Scotty.NET

Genérico

   public static DataTable ToTableValuedParameter<T, TProperty>(this IEnumerable<T> list, Func<T, TProperty> selector)
    {
        var tbl = new DataTable();
        tbl.Columns.Add("Id", typeof(T));

        foreach (var item in list)
        {
            tbl.Rows.Add(selector.Invoke(item));

        }

        return tbl;

    }
Martea avatar Feb 07 '2014 08:02 Martea