Backry SQLBulkCopy per SQL Server 2008 R2

.net c# sqlbulkcopy sql-server sql-server-2008-r2

Domanda

Sono fondamentalmente dal database di base e nuovo di roba .net. Per favore, sopportami se la mia domanda sembra sciocca.

Sto usando SqlBulkCopy nel mio codice per trasferire dati da un server SQL ad altri. Ma spesso non funziona a causa di problemi di rete. Per evitare che io abbia intenzione di fare due cose

  1. Ridurre le dimensioni del batch (da 5000 a 1000) e aumentare il timeout (da 3 minuti a 1 minuto)

  2. Implementare la logica di riprova

La mia domanda è

  1. Qual è il modo migliore per implementare i tentativi, ad esempio a livello di tabella o a livello di batch (se possibile)?
  2. Ho trovato alcuni frame work per resiliency SQL Azure qui: https://msdn.microsoft.com/en-us/library/hh680934(v=pandp.50).aspx Abbiamo qualcosa di simile per SQL Server 2008 R2?

Codice di esempio che sto utilizzando:

  private void BulkCopyTable(string schemaName, string tableName)
    {using (var reader = srcConnection.ExecuteReader($"select * from [{SourceDBName}].[{schemaName}].[{tableName}]"))
            {
                const SqlBulkCopyOptions bulkCopyOptions = SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.FireTriggers |
                                                           SqlBulkCopyOptions.KeepNulls | 
                                                           SqlBulkCopyOptions.KeepIdentity;

                using (var bcp = new SqlBulkCopy(dstConnection.ConnectionString, bulkCopyOptions))
                {
                    const int threeMinutes = 60*3;
                    bcp.BulkCopyTimeout = threeMinutes; //Timeout is for a single batch
                    bcp.BatchSize = 5000;
                    bcp.DestinationTableName = $"[{DestinationDB}].[{schemaName}].[{tableName}]";
                    bcp.EnableStreaming = true;
                    foreach (var col in table.Columns.Cast<Column>().Where(c => !c.Computed))
                    {
                        bcp.ColumnMappings.Add(col.Name, col.Name);
                    }
                    bcp.WriteToServer(reader);
                }
            }
        }

Risposta popolare

Un approccio semplice è:

  1. Implementare i lotti da soli. Ciò si traduce in una minore inefficienza poiché SqlBulkCopy deve interrogare i metadati per ogni chiamata WriteToServer . Quindi non rendere i lotti troppo piccoli. Sperimentare.
  2. Inserisci in una tabella temporanea (non una tabella #temp ma una duratura in modo da poter perdere la connessione e continuare).
  3. Quindi, eseguire un insert...select come passaggio finale per spostare le righe dalla tabella temporanea alla tabella reale.

Questa danza suddivide il lavoro in batch ripetibili ma agisce come se fosse una transazione.

Se non hai bisogno di atomicità puoi lasciarla al punto (1).



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é