2010-08-14 5 views
1

J'essaye d'écrire l'application Windows pour obtenir des données à partir de Fox Pro DB, et l'insérer dans Sql Server 2008 db.insérer des données à la base de données dans la performance de la boucle

J'ai écrit du code, mais cela fonctionne très lentement. rowsCount plus de 1 million Mon code ci-dessous:

OleDbConnection cn = new OleDbConnection(foxProConnectionString); 
SqlConnection cSql = new SqlConnection(sqlServerConnectionString); 
cSql.Open(); 

OleDbCommand ocmd = new OleDbCommand("Select * from " + table, cn); 
OleDbDataAdapter sda = new OleDbDataAdapter(ocmd); 
DataTable dt = new DataTable(); 
sda.Fill(dt); 
SqlCommand mySqlcmd = new SqlCommand(); 
mySqlcmd.Connection = cSql; 

for (int i = 0; i < dt.Rows.Count; i++) 
{ 
    mySqlcmd.CommandText = "INSERT INTO sqlTable (column1, column2, column3) VALUES ("+dt.Rows[i][dt.Columns.IndexOf("column1")] + ",'" 
              + DoOper1(dt.Rows[i]dt.Columns.IndexOf("column2")]) + "','" 
              + dt.Rows[i][dt.Columns.IndexOf("column3")] + "')"; 

    mySqlcmd.ExecuteNonQuery(); 
} 

Je ne peux pas utiliser la copie en bloc, les colonnes de base de données peut être différente l'ordre dans certaines tables source. Aussi j'obtiens l'erreur:

The CLR has been unable to transition from COM context 0x54afe8 to COM context 0x54b158 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

comment puis-je résoudre un ensemble de mon problème?

+0

Quelle est la lenteur de la lenteur? Par exemple, l'exécution de sql pour mettre à jour la colonne de mot de passe dans notre table d'utilisateurs de 25 millions d'enregistrements a pris environ 12 heures. –

+0

Supprimez tous vos index et contraintes de cette table et restaurez-les après le chargement des données. – Rup

+0

obtenir des données à partir de l'opération foxPro et insérer l'opération environ 1 million de lignes prend environ 3 minutes. – loviji

Répondre

2

Je pense qu'il existe des moyens de contourner vos problèmes de copie en bloc et je vous suggère de travailler dessus plutôt que d'essayer d'examiner pourquoi une technologie lente est lente. Vous dites que les raisons pour lesquelles vous ne pouvez pas utiliser la copie en bloc sont parce que l'ordre des colonnes de la base de données peut être différent dans certaines tables source. Ma réponse à cela est, pourquoi est-ce important? Si vous utilisez l'objet SqlBulkCopy, n'avez-vous pas un contrôle total sur la façon dont les colonnes des tables source correspondent aux colonnes des tables de destination? (Avez-vous essayé d'utiliser l'objet SqlBulkCopy?) Vous dites également que vous pouvez un message d'erreur sur un programme qui ne répond pas. On dirait que c'est lié à COM. Je ne vois pas pourquoi ce serait un problème avec Bulk Copy sur quelque chose qui prend encore plus de temps à s'exécuter. Si nécessaire, vous devrez peut-être effectuer des opérations de copie en masse en lots plus petits (peut-être en terminant/validant complètement les lots avant de commencer le suivant?) Afin que votre programme ne perde pas le contrôle de son exécution. Cela aide-t-il ou provoque-t-il d'autres questions pouvant mener à une réponse?

Modifier: Pouvez-vous faire quelque chose comme ça?

System.Data.SqlClient.SqlBulkCopy bc = new System.Data.SqlClient.SqlBulkCopy("..."); 

// Begin a loop to process managable-size batches of source data. 

using (System.Data.DataTable dtTarget = new System.Data.DataTable("sqlTable")) 
{ 

    // Populate dtTarget with the data as it should appear 
    // on the SQL Server side. 
    // If the mapping is simple, you may be able to use 
    // bc.ColumnMappings instead of manually re-mapping. 

    bc.DestinationTableName = "sqlTable"; 
    bc.WriteToServer(dtTarget); 
} 

// End loop. 
+0

J'ai utilisé sqlBulkCopy, peut-être que je ne connais pas toutes les fonctionnalités de SqlBulkCopy. Par exemple, je lis les données de la table source. Puis-je faire une opération avec certaines données de colonnes, puis l'écrire sur le serveur SQL, où la table existante avec des données? Si oui, comment puis-je faire cela? – loviji

+0

Vous avez un contrôle total sur la façon dont les colonnes et les lignes sont soumises au serveur SQL, car vous pouvez créer un DataTable avec des données. J'ai ajouté un exemple de code à ma réponse. Y a-t-il un problème avec l'utilisation de code comme celui-ci? – BlueMonkMN

Questions connexes