Je travaille avec 2 serveurs SQL 2008 sur différentes machines. Les noms de serveur sont source.ex.com
et destination.ex.com
.SqlBulkInsert avec un DataTable à un serveur lié
destination.ex.com
est lié à source.ex.com
et les autorisations appropriées sont en place pour source.ex.com
d'écrire dans une base de données appelée bacon-wrench
sur destination.ex.com
Je suis connecté en source.ex.com
par SMS et testé cette requête (avec succès):
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (4,6);
Dans un C# .NET 4.0 WebPage je me connecte à source.ex.com
et exécuter une requête similaire (avec succès):
using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
c.Open();
String sql = @"
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (34,56);";
using(SqlCommand cmd = new SqlCommand(sql, c))
{
cmd.ExecuteNonQuery();
}
}
Pour les petits ensembles d'instructions d'insertion (par exemple 20 ou moins) faire quelque chose comme ça joue bien:
using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
c.Open();
String sql = @"
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (34,56);
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (22,11);
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (33,55);
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (1,2);";
using(SqlCommand cmd = new SqlCommand(sql, c))
{
cmd.ExecuteNonQuery();
}
}
Je suis en train de faire quelque chose comme ça avec environ 20 000 dossiers. La méthode ci-dessus prend 11 minutes à compléter - ce que je suppose est le serveur qui me sreaming pour en faire une sorte d'opération en vrac. A partir d'autres threads StackOverflow, la classe SqlBulkCopy
a été recommandée et prend comme paramètre DataTable
, parfait!
Alors je construis un DataTable et d'essayer d'écrire sur le serveur (échec):
DataTable dt = new DataTable();
dt.Columns.Add("PunchID", typeof(int));
dt.Columns.Add("BaconID", typeof(int));
for(int i = 0; i < 20000; i++)
{
//I realize this would make 20000 duplicate
//rows but its not important
dt.Rows.Add(new object[] {
11, 33
});
}
using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
c.Open();
using(SqlBulkCopy bulk = new SqlBulkCopy(c))
{
bulk.DestinationTableName = "[destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]";
bulk.ColumnMappings.Add("PunchID", "PunchID");
bulk.ColumnMappings.Add("BaconID", "BaconID");
bulk.WriteToServer(dt);
}
}
EDIT2: Le message ci-dessous est ce que je tente de corriger:
La plante page web à bulk.WriteToServer(dt);
avec un message d'erreur Database bacon-wrench does not exist please ensure it is typed correctly.
Qu'est-ce que je fais mal? Comment puis-je changer cela pour le faire fonctionner?
EDIT1:
j'ai pu accélérer la requête de manière significative en utilisant la syntaxe ci-dessous. Mais c'est encore très lent pour un si petit ensemble d'enregistrements.
using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
c.Open();
String sql = @"
INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES
(34,56),
(22,11),
(33,55),
(1,2);";
using(SqlCommand cmd = new SqlCommand(sql, c))
{
cmd.ExecuteNonQuery();
}
}
Oh Noes! Je vais essayer comme vous l'avez suggéré. –