Se si utilizza SQL 2008, è possibile creare una stored procedure che accetta un parametro Valued Table (TVP) e utilizzare per eseguire ADO.net la stored procedure e passare un DataTable ad esso:
in primo luogo, è necessario creare il tipo in SQL Server:
CREATE TYPE [dbo].[udt_UserId] AS TABLE(
[UserId] [int] NULL
)
Quindi, è necessario scrivere una stored procedure che accetta questo tipo come parametro:
CREATE PROCEDURE [dbo].[usp_DoSomethingWithTableTypedParameter]
(
@UserIdList udt_UserId READONLY
)
AS
BEGIN
SELECT userId, username
FROM Users
WHERE userId IN (SELECT UserId FROM @UserIDList)
END
Ora da .net, non è possibile utilizzare LINQ poiché non supporta ancora i parametri di tabella; quindi devi scrivere una funzione che faccia semplicemente il vecchio ADO.net, prende un DataTable e lo passa alla stored procedure: ho scritto una funzione generica che uso che può fare questo per qualsiasi stored procedure, purché richieda solo un parametro tipizzato da tabella, indipendentemente da cosa sia;
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;
}
}
Quindi è possibile scrivere le funzioni DAL che utilizzano questa funzione di utilità con i nomi effettivi delle stored procedure; per costruire l'esempio nella sua interrogazione, qui è ciò che il codice sarebbe simile:
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 il parametro "Connessione" di cui sopra - Io in realtà uso questo tipo di funzione in una classe DataContext parziale di estendere LINQ DataContext con la mia funzionalità TVP, e uso ancora la sintassi (usando il contesto var = new MyDataContext()) con questi metodi.
Questo funziona solo se si utilizza SQL Server 2008 - si spera che lo sia e in caso contrario, questa potrebbe essere una buona ragione per eseguire l'aggiornamento! Naturalmente nella maggior parte dei casi e in ambienti di produzione di grandi dimensioni non è così facile, ma FWIW penso che questo sia il modo migliore per farlo se hai la tecnologia disponibile.
Le virgole devono essere tra le stringhe, non all'interno di una stringa. –
Le virgole separano ciascun ID utente – chobo
Quale versione di SQL-Server? –