SqlBulkCopy e DataTables con relazione padre / figlio nella colonna Identity

.net c# sqlbulkcopy sql-server

Domanda

Abbiamo bisogno di aggiornare diverse tabelle che hanno relazioni parent / child basate su una chiave primaria Identity nella tabella padre, a cui fa riferimento una o più tabelle figlio come chiave esterna.

  • A causa dell'elevato volume di dati, vorremmo costruire queste tabelle in memoria, quindi utilizzare SqlBulkCopy da C # per aggiornare il database in massa dal DataSet o dai singoli DataTable.
  • Vorremmo inoltre farlo in parallelo, da più thread, processi e possibilmente clienti.

Il nostro prototipo in F # mostra molte promesse, con un aumento delle prestazioni di 34x, ma questo codice forza valori di Identità noti nella tabella genitore. Quando non forzato, la colonna Identity viene generata correttamente nel database quando SqlBulkCopy inserisce le righe, ma i valori di Identity NON vengono aggiornati nella DataTable in memoria. Inoltre, anche se lo fossero, non è chiaro se il DataSet corregga correttamente le relazioni padre / figlio, in modo che le tabelle figlio possano successivamente essere scritte con valori di chiave esterna corretti.

Qualcuno può spiegare come avere SqlBulkCopy aggiorna i valori di identità e inoltre come configurare un DataSet in modo da conservare e aggiornare le relazioni padre / figlio, se questo non viene eseguito automaticamente quando un DataAdapter viene chiamato a FillSchema sui singoli DataTable.

Risposte che non sto cercando:

  • Leggi il database per trovare il valore di Identità corrente più alto, quindi incrementalo manualmente durante la creazione di ciascuna riga padre. Non funziona per più processi / client e, a quanto ho appreso, le transazioni non riuscite potrebbero causare l'omissione di alcuni valori Identity, quindi questo metodo potrebbe rovinare la relazione.
  • Scrivi le righe padre una alla volta e richiedi il valore Identity. Ciò sconfigge almeno alcuni dei guadagni ottenuti usando SqlBulkCopy (sì, ci sono molte più righe figlio rispetto a quelle dei genitori, ma ci sono ancora molte righe parentali).

Simile alla seguente domanda senza risposta:

Risposta popolare

Prima di tutto: SqlBulkCopy non è possibile fare ciò che vuoi. Come suggerisce il nome, è solo una "strada a senso unico". Metto i dati in SQL Server il più velocemente possibile. È la versione .Net del vecchio comando di copia bulk che importa file di testo non elaborati in tabelle. Quindi non è possibile ripristinare i valori di identità se si utilizza SqlBulkCopy.

Ho elaborato molti dati in serie e ho affrontato questo problema più volte. La soluzione dipende dalla tua architettura e dalla distribuzione dei dati. Ecco alcune idee:

  • Creare un set di tabelle di destinazione per ogni thread, importare in queste tabelle. Alla fine unisciti a queste tabelle. La maggior parte di questo può essere implementata in un modo abbastanza generico in cui si generano automaticamente tabelle denominate TABLENAME_THREAD_ID dalle tabelle denominate TABLENAME.

  • Sposta la generazione dell'ID completamente fuori dal database. Ad esempio, implementare un servizio web centrale che genera gli ID. In tal caso non si dovrebbe generare un ID per chiamata, ma piuttosto generare intervalli di ID. Altrimenti la rete in testa diventa di solito un collo di bottiglia.

  • Prova a generare ID i tuoi dati. Se è possibile, il tuo problema sarebbe sparito. Non dire "non è possibile" digiunare. Forse puoi usare gli id ​​stringa che possono essere ripuliti in una fase di post-elaborazione?

E ancora una osservazione: un aumento del fattore 34 quando si usano i suoni di BulkCopy a parere piccolo. Se vuoi inserire velocemente i dati, assicurati che il tuo database sia configurato correttamente.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché