SqlBulkCopy et DataTables avec relation parent / enfant sur la colonne d'identité

.net c# sqlbulkcopy sql-server

Question

Nous avons besoin de mettre à jour plusieurs tables ayant des relations parent / enfant basées sur une clé primaire Identity dans la table parent, désignée par une ou plusieurs tables enfants comme une clé étrangère.

  • En raison du volume élevé de données, nous aimerions construire ces tables en mémoire, puis utiliser SqlBulkCopy à partir de C # pour mettre à jour la base de données en masse à partir du DataSet ou des DataTables individuels.
  • Nous aimerions également le faire en parallèle, à partir de plusieurs threads, processus et éventuellement clients.

Notre prototype en F # est très prometteur, avec une augmentation de 34 fois des performances, mais ce code impose des valeurs d'identité connues dans la table parente. Lorsqu'elle n'est pas forcée, la colonne Identity est correctement générée dans la base de données lorsque SqlBulkCopy insère les lignes, mais les valeurs Identity NE sont PAS mises à jour dans le DataTable en mémoire. De plus, même s'ils l'étaient, il n'est pas clair si le DataSet corrigera correctement les relations parent / enfant, de sorte que les tables enfants puissent ensuite être écrites avec les valeurs de clé étrangère correctes.

Quelqu'un peut-il expliquer comment mettre à jour SqlBulkCopy les valeurs d'identité, et comment configurer un DataSet afin de conserver et de mettre à jour les relations parent / enfant, si cela n'est pas fait automatiquement lorsqu'un DataAdapter est appelé à FillSchema sur les DataTables individuels.

Réponses que je ne cherche pas:

  • Lisez la base de données pour rechercher la valeur d'identité la plus élevée actuelle, puis incrémentez-la manuellement lors de la création de chaque ligne parente. Ne fonctionne pas pour plusieurs processus / clients et, si j'ai bien compris, les transactions ayant échoué peuvent entraîner l'omission de certaines valeurs d'identité. Cette méthode peut donc fausser la relation.
  • Ecrivez les lignes parent une par une et demandez la valeur Identity. Cela annule au moins une partie des gains obtenus en utilisant SqlBulkCopy (oui, il y a beaucoup plus de lignes enfants que de lignes mères, mais il en reste encore beaucoup).

Semblable à la question suivante sans réponse:

Réponse populaire

Tout d'abord: SqlBulkCopy n'est pas possible de faire ce que vous voulez. Comme son nom l'indique, il ne s'agit que d'une "rue à sens unique". Je déplace les données dans le serveur SQL aussi rapidement que possible. C'est la version .Net de l'ancienne commande de copie en bloc qui importe des fichiers texte bruts dans des tableaux. Il n'y a donc aucun moyen de récupérer les valeurs d'identité si vous utilisez SqlBulkCopy.

J'ai effectué beaucoup de traitement de données en bloc et j'ai rencontré ce problème plusieurs fois. La solution dépend de votre architecture et de la distribution des données. Voici quelques idées:

  • Créez un ensemble de tables cible pour chaque thread, importez-les dans ces tables. À la fin, rejoignez ces tables. La plupart de ces opérations peuvent être implémentées de manière assez générique en générant automatiquement des tables nommées TABLENAME_THREAD_ID à partir de tables nommées TABLENAME.

  • Déplacez complètement la génération d'ID de la base de données. Par exemple, implémentez un service Web central qui génère les identifiants. Dans ce cas, vous ne devez pas générer un identifiant par appel, mais plutôt des plages d'identifiants. Sinon, les frais généraux du réseau deviennent généralement un goulot d'étranglement.

  • Essayez de générer des identifiants sur vos données. Si c'était possible, votre problème aurait disparu. Ne dites pas "ce n'est pas possible" de jeûner. Peut-être que vous pouvez utiliser des identifiants de chaîne qui peuvent être nettoyés dans une étape de post-traitement?

Et encore une remarque: une augmentation du facteur 34 lors de l’utilisation de BulkCopy semble trop faible dans l’opinion. Si vous souhaitez insérer rapidement des données, assurez-vous que votre base de données est configurée correctement.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow