Si está utilizando SQL Server 2008, puede crear un procedimiento almacenado que acepta un parámetro valorado Tabla (TVP) y el uso de ADO.net para ejecutar el procedimiento y se almacena pasar una tabla de datos a la misma:
en primer lugar, es necesario crear el tipo de servidor SQL:
CREATE TYPE [dbo].[udt_UserId] AS TABLE(
[UserId] [int] NULL
)
Entonces, es necesario escribir un procedimiento almacenado que acepta este tipo como un parámetro:
CREATE PROCEDURE [dbo].[usp_DoSomethingWithTableTypedParameter]
(
@UserIdList udt_UserId READONLY
)
AS
BEGIN
SELECT userId, username
FROM Users
WHERE userId IN (SELECT UserId FROM @UserIDList)
END
Ahora desde .net, no puede usar LINQ ya que aún no es compatible con los parámetros de tabla de valores; por lo tanto, debe escribir una función que haga simple ADO antiguo.net, toma una DataTable y la pasa al procedimiento almacenado: he escrito una función genérica que uso que puede hacer esto para cualquier procedimiento almacenado, siempre y cuando solo tome el parámetro de una tabla, independientemente de lo que sea;
public static int ExecStoredProcWithTVP(DbConnection connection, string storedProcedureName, string tableName, string tableTypeName, DataTable dt)
{
using (SqlConnection conn = new SqlConnection(connection.ConnectionString))
{
SqlCommand cmd = new SqlCommand(storedProcedureName, conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter p = cmd.Parameters.AddWithValue(tableName, dt);
p.SqlDbType = SqlDbType.Structured;
p.TypeName = tableTypeName;
conn.Open();
int rowsAffected = cmd.ExecuteNonQuery(); // or could execute reader and pass a Func<T> to perform action on the datareader;
conn.Close();
return rowsAffected;
}
}
Luego puede escribir las funciones DAL que utilizan esta función de utilidad con los nombres reales de los procedimientos almacenados; para construir en el ejemplo en su pregunta, esto es lo que el código se vería así:
public int usp_DoSomethingWithTableTypedParameter(List<UserID> userIdList)
{
DataTable dt = new DataTable();
dt.Columns.Add("UserId", typeof(int));
foreach (var userId in updateList)
{
dt.Rows.Add(new object[] { userId });
}
int rowsAffected = ExecStoredProcWithTVP(Connection, "usp_DoSomethingWithTableTypedParameter", "@UserIdList", "udt_UserId", dt);
return rowsAffected;
}
Nota el parámetro de "conexión" más arriba - en realidad yo uso este tipo de función en una clase DataContext parcial para extender LINQ DataContext con mi funcionalidad TVP, y aún uso la sintaxis (usando var context = new MyDataContext()) con estos métodos.
Esto solo funcionará si está usando SQL Server 2008 - con suerte lo es y, de lo contrario, ¡esta podría ser una buena razón para actualizar! Por supuesto, en la mayoría de los casos y en entornos de producción grandes esto no es tan fácil, pero FWIW creo que esta es la mejor manera de hacerlo si tiene la tecnología disponible.
Las comas tienen que ser entre las cuerdas, no dentro de una cadena. –
Las comas separan cada userid – chobo
¿Qué versión de SQL-Server? –