SqlBulkCopy.WriteToServer n'obéit pas de manière fiable à BulkCopyTimeout

.net c# sqlbulkcopy sql-server-2008 timeout

Question

Je dois compter les exceptions de timeout séquentielles de SqlBulkCopy. Pour tester cela, j'utilise une application externe pour démarrer une transaction et verrouiller la table cible.

SqlBulkCopy lève une exception de délai d'expiration uniquement lorsque prévu. Nous avons essayé d'utiliser une connexion et une transaction externes, ainsi qu'une chaîne de connexion et une transaction interne. Avec la connexion et la transaction externes, l'attente infinie n'a jamais été l'ouverture de la connexion, le début ou la .WriteToServer() la transaction, mais toujours à .WriteToServer() .

Existe-t-il une approche permettant à SqlBulkCopy.WriteToServer() manière fiable une exception de délai d'expiration lorsqu'il a atteint sa limite .BulkCopyTimeout ?

public void BulkCopy(string connectionString, DataTable table, int bulkTimeout)
{
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
        connectionString, 
        SqlBulkCopyOptions.UseInternalTransaction))
    {
    bulkCopy.BulkCopyTimeout = bulkTimeout;//e.g. 120 sec.
    //... fill with data, map columns...
    bulkCopy.WriteToServer(table);
    // ^^^^ waits indefinitely, doesn't throw until *after*
    //      the lock is released.
    }
}

Je préfère laisser les exceptions bouillonner plutôt que de les gérer dans le cadre du bloc using , mais je peux toujours les renvoyer. Merci beaucoup pour toute idée.

Mise à jour 1:

Toujours pas de résolution. Comportement intéressant découvert cependant - une commande SqlCommand normale lève une exception TimeoutException comme prévu pendant le même verrou qui oblige la méthode SqlBulkCopy.WriteToServer à se bloquer indéfiniment.

Voici des approches que nous avons essayées - et qui ont échouées - pour que SqlBulkCopy.WriteToServer lise régulièrement les délais d'attente lorsque cela est prévu:

  • MARS (Multiple Active Result Sets) activé / désactivé
  • TableLock on vs. off
  • Destination sous forme de table de segmentation ou de table indexée
  • Valeurs BulkTimeout plus longues / plus courtes (10 secondes à 5 minutes)
  • Transaction interne ou externe

Pour le moment, comme solution de contournement, j'intervertis a) en plaçant l'appel WriteToServer dans un wrapper asynchrone afin de pouvoir le chronométrer moi-même, et b) en appelant une seule fois WriteToServer; Après les délais d'attente, attendez qu'un SqlCommand normal réussisse avant de réessayer WriteToServer. En utilisant ces approches, je suis au moins capable de garder le contrôle du flux d'exécution.

Réponse acceptée

Avez-vous essayé de passer l'option SqlBulkOptions.TableLock à SqlBulkCopy? Cette option (citation) signifie qu'elle:

Obtenez un verrou de mise à jour en bloc pour la durée de l'opération de copie en bloc.

Ainsi, si un autre processus verrouille la table, cela empêchera le verrouillage et, en théorie, un dépassement de délai fiable.

Mettre à jour:
J'ai créé mon propre harnais de test et je ne peux pas me reproduire. Pour verrouiller la table, j'ai lancé une transaction dans SSMS en effectuant une opération SELECT * FROM TargetTable WITH (HOLDLOCK) . J'ai utilisé la même méthode BulkCopy que vous avez incluse dans la question, à l'aide de transactions internes, avec un délai de chargement en bloc de 30 secondes. Chaque tentative de copie en bloc expire comme prévu après 30 secondes. Il réussit ensuite lorsque j'annule la transaction SSMS.

J'utilisais SQL Server 2008 Express, .NET 3.5.

Ce n'est pas quelque chose comme après la première tentative, le délai de chargement en bloc n'est pas passé correctement? c'est-à-dire que ce n'est pas en quelque sorte réglé sur "indéfini".

Mise à jour 2:
Également activé la prise en charge de plusieurs ensembles de résultats actifs dans la chaîne de connexion, l'expiration du délai est toujours constante pour moi à chaque fois.


Réponse populaire

J'ai eu ce problème plus tard et pour résoudre ce problème, définissez BulkCopyTimeout à zéro.

bulkCopy.BulkCopyTimeout = 0;


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