Retouche SQLBulkCopy pour SQL Server 2008 R2

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

Question

Je viens de la base de données et je suis novice en matière de .net. S'il vous plaît supporter avec moi si ma question semble stupide.

J'utilise SqlBulkCopy dans mon code pour transférer des données d'un serveur SQL à un autre. Mais il échoue fréquemment en raison de problèmes de réseau. Pour éviter que je prévoie de faire deux choses

  1. Diminuer la taille du lot (de 5 000 à 1 000) et augmenter le délai d'attente (de 3 min à 1 min)

  2. Implémenter la logique de nouvelle tentative

Ma question est

  1. Quel est le meilleur moyen d'implémenter une nouvelle tentative, c'est-à-dire au niveau de la table ou du lot (si possible)?
  2. J'ai trouvé un cadre pour la résilience de SQL Azure ici: https://msdn.microsoft.com/en-us/library/hh680934(v=pandp.50).aspx Avons-nous quelque chose de similaire pour SQL Server 2008 R2?

Exemple de code que j'utilise:

  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);
                }
            }
        }

Réponse populaire

Une approche simple consiste à:

  1. Implémentez vous-même les lots. Cela entraîne une inefficacité mineure, car SqlBulkCopy doit interroger les métadonnées pour chaque appel WriteToServer . Donc, ne faites pas les lots trop petits. Expérience.
  2. Insérer dans une table temporaire (non pas une table #temp , mais une table durable pour que vous puissiez perdre la connexion et continuer).
  3. Ensuite, exécutez une insert...select comme dernière étape pour déplacer les lignes de la table temporaire vers la table réelle.

Cette danse divise le travail en lots réutilisables, mais agit comme s'il s'agissait d'une transaction.

Si vous n'avez pas besoin d'atomicité, vous pouvez le laisser à l'étape (1).



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi