2012-05-25 215 views
7

Sto scrivendo un'applicazione .NET che scrive dati su SQL Server 2008r2. Ho due opzioni per inserire i dati, o posso creare una dichiarazione di inserimento stringa di grandi dimensioni e inviarlo come comando di testo, oppure posso raccogliere i dati in un DataTable .NET e passarlo come parametro valutato a livello di tabella. Quali sono i vantaggi e i costi di ciascun metodo?È meglio passare inserti di grandi dimensioni a SQL Server come parametro con valori di tabella o come istruzione di inserimento stringa?

(sto omettendo una buona dose di codice dal momento che sto solo chiedendo circa i relativi benefici, non la sintassi specifica)

esempio:

Opzione 1:

string insert = @"insert into MyTable (id, val) values 
     (1, 'a'),(2,'b'),(3,'c'),(4,'d');" 

Opzione 2 :

DataTable dt = new DataTable(); 
    dt.Columns.Add("id", typeof(int)); 
    dt.Columns.Add("val", typeof(string)); 
    .... 
    create procedure uspMyProc 
        @tt ttMyTableType readonly 
       as 
       begin 
        insert into TestTable1 (id, strValue) 
        select myId, myVal from @tt; 
       end" 

Grazie per qualsiasi aiuto.

+0

Opzione # 3. Utilizzare SqlCommand. La struttura può essere dinamica (* se e solo se necessario *), mantenendo i parametri parametrizzati. –

+0

(Molti inserimenti SqlCommand sono molto veloci quando le transazioni vengono utilizzate correttamente.) –

risposta

7

Opzione 3: In primo luogo vorrei popolare la stored procedure inserto con pena la propria istruzione di inserimento di parametri e chiamarlo più volte in un ciclo dal codice C#:

Opzione 4: Se hai veramente lotti di righe da inserire, forse hai bisogno di guardare nello SqlBulkCopy class. Consuma DataTable, DataRow o IDataReader. È possibile effettuare una IDataReader da un elenco di oggetti che utilizzano un codice personalizzato, una domanda di questo genere viene chiesto qui:

Get an IDataReader from a typed List


direi che dipende.

Se si desidera passare molte righe di parametri in forma tabellare, per qualsiasi motivo, utilizzare un parametro con valori di tabella - questo è il motivo per cui è presente.

Ho visto l'Opzione 1: alcuni codici DAL generici avrebbero scritto un "batch" SQL di comandi da eseguire. Ha funzionato, ma non ha dato alcuna difesa contro gli attacchi di iniezione. SQL parametrizzato fa.


Detto questo, vorrei favorire chiamando lo sproc inserto volta per ogni riga da inserire dal codice - le chiamate sarà completamente parametrizzato e le prestazioni va bene. Se le prestazioni diventano un problema, gradirei l'opzione 4.

+0

aiuta anche a difendersi da SQL Injection – n8wrl

+0

Grazie. Non ero a conoscenza della classe SqlBulkCopy. Penso che sia esattamente quello che sto cercando. – Sako73

5

Quanto è grande? Se è enorme, niente batte SqlBulkCopy. Ho effettivamente trovato le prestazioni TVP deludenti. Per il riutilizzo del piano di query, sono un fan delle dichiarazioni parametriche e di riutilizzo massiccio. Dapper può aiutare in questo modo, consentendo di passare un elenco di oggetti a una query: aggiungerà quindi i parametri nominati per oggetto in base al nome del membro, a molte migliaia di operazioni al secondo. Ad esempio:

conn.Execute(
    "insert foo (Id,Name) values (@Id,@Name)", 
    listOfObjects); 

Ciò scorrere la lista e utilizzare .Id e .Name da ogni oggetto a sua volta per eseguire la query.

+0

Fornire un collegamento a Drapper – Paparazzi

+0

@Blam o digitare "dapper" in nuget oppure: http://code.google.com/p/dapper-dot-net/ (è lo stack personalizzato che usiamo per high-perf accesso ai dati qui allo stackoverflow) –

4

Valori è limitata a 1000

e valori sembra avere alcune prestazioni emette

Insert Performance Issues With Multiple Values

Io uso TVP per l'inserimento di migliaia di righe e funziona benissimo per me. Uso una raccolta di elenchi come sorgente TVP poiché DataTable ha un sovraccarico. Inserisci le righe ordinate dal PK se puoi.

Con ciò detto ho intenzione di provare la risposta di Marc Gravell.

JNK ha una sfiducia generale nei confronti di TVP.

+0

sei sicuro di 'DataTable' e overhead vs Enumerable type e ogni record con un round trip da C# a sqlserver su ogni record? (Ho raggiunto questa domanda solo perché ho resarch questo problema) per la mia domanda [http://stackoverflow.com/questions/34365407/c-sharp-sql-server-best-way-to-delete-multiple-rows-in- one-go-using-a-stor # 34366719] in cui provo a usarlo per le eliminazioni multiple per ID record. –

+0

_ "I dati sono strutturati come serie di righe fortemente tipizzate sul client e si trasformano in un insieme di righe fortemente tipizzate sul server in un unico round trip" _ da - https: //lennilobel.wordpress .com/2009/07/29/sql-server-2008-table-value-parameters-and-c-custom-iterators-a-match-made-in-heaven/ –

+0

@ Robb_2015 Sei sicuro di aver letto la mia risposta? I valori indicano chiaramente l'opzione 1 :. Come per Option2, lo dichiaro (TVP) funziona alla grande. In nessun punto della mia risposta, dichiaro che un TVP non è stato tipizzato in maniera rigida, né che ciò si traduce in più viaggi di andata e ritorno. – Paparazzi

Problemi correlati