È possibile inviare una raccolta di ID come parametro SQL ADO.NET?
Domanda
Eg. posso scrivere qualcosa di simile a questo codice:
public void InactiveCustomers(IEnumerable<Guid> customerIDs)
{
//...
myAdoCommand.CommandText =
"UPDATE Customer SET Active = 0 WHERE CustomerID in (@CustomerIDs)";
myAdoCommand.Parameters["@CustomerIDs"].Value = customerIDs;
//...
}
L'unico modo che conosco è unire il mio IEnumerable e quindi utilizzare la concatenazione di stringhe per creare la mia stringa SQL.
Soluzione
Generalmente il modo in cui lo fai è passare in un elenco di valori separato da virgole e, all'interno della tua procedura memorizzata, analizzare l'elenco e inserirlo in una tabella temporanea, che puoi quindi utilizzare per i join. A partire da SQL Server 2005 , questa è una pratica standard per la gestione di parametri che devono contenere array.
Ecco un buon articolo su vari modi per affrontare questo problema:
Passaggio di un elenco / array a una procedura memorizzata di SQL Server
Ma per SQL Server 2008 , possiamo finalmente passare le variabili della tabella nelle procedure, definendo prima la tabella come tipo personalizzato.
C'è una buona descrizione di questo (e di altre funzionalità del 2008) in questo articolo:
Introduzione alle nuove funzionalità di programmabilità T-SQL in SQL Server 2008
Altri suggerimenti
Puoi SQL 2008 . Non è uscito da molto tempo, ma è disponibile.
Come menzionato in un commento , Erland Sommarskog ha scritto una serie di articoli su questo argomento (linkato di seguito). Gli articoli sono molto approfonditi e possono servire come materiale di riferimento. Sebbene siano specifici di SQL Server (T-SQL), alcune delle tecniche menzionate potrebbero funzionare anche per altri RDBMS (come l'utilizzo di un tipo di dati XML
):
Array ed elenchi in SQL Server 2008 utilizzando la tabella Parametri valutati :
- Parametri con valori di tabella (TVP)
Array ed elenchi in SQL Server 2005 e oltre Quando i TVP non lo tagliano :
- serializzazione di stringhe e deserializzazione di valori scalari
- SQLCLR
- passando i dati dell'elenco strutturato tramite il tipo di dati XML
- SQL dinamico
È possibile utilizzare il tipo di parametro xml:
CREATE PROCEDURE SelectByIdList(@productIds xml) AS
DECLARE @Products TABLE (ID int)
INSERT INTO @Products (ID) SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @productIds.nodes('/Products/id') as ParamValues(ID)
SELECT * FROM
Products
INNER JOIN
@Products p
ON Products.ProductID = p.ID
No. I parametri sono come i valori SQL nell'obbedire alla prima forma normale , in sostanza, ci può solo sii uno ...
Come probabilmente saprai, generare stringhe SQL è un affare rischioso: ti lasci aperto a un iniezione SQL attacco . Finché hai a che fare con GUID in buona fede, dovresti andare bene, ma altrimenti devi essere sicuro di ripulire il tuo input.
Non è possibile passare un elenco come singolo parametro SQl. Puoi string.Unire (',') i GUID come " 0000-0000-0000-0000, 1111-1111-1111-1111 " ma questo sarebbe alto sul sovraccarico del database e davvero non ottimale. E devi passare l'intera stringa come singola istruzione dinamica concatenata, non puoi aggiungerla come parametro.
Domanda:
Da dove prendi il tuo elenco di ID che rappresentano i clienti inattivi?
Il mio suggerimento è di affrontare il problema in modo leggermente diverso. Sposta tutta quella logica nel database, qualcosa del tipo:
Create procedure usp_DeactivateCustomers
@inactive varchar(50) /*or whatever values are required to identify inactive customers*/
AS
UPDATE Customer SET c.Active = 0
FROM Customer c JOIN tableB b ON c.CustomerID = b.CustomerID
WHERE b.someField = @inactive
E chiamalo come procedura memorizzata:
public void InactiveCustomers(string inactive)
{
//...
myAdoCommand.CommandText =
"usp_DeactivateCustomers";
myAdoCommand.Parameters["@inactive"].Value = inactive;
//...
}
Se in un database esiste un elenco di GUID, perché devo trovarli; metterli in un elenco generico; svolgere l'elenco in una variabile CSV / XML / Table, solo per presentarli nuovamente al DB ????? Sono già lì! Mi sto perdendo qualcosa?