Dans .Net1.1, il n'est pas très pratique d'insérer par lots toutes les données de l'ensemble du DataTable dans la base de données ou de migrer entre différentes sources de données. Dans .Net2.0, plusieurs nouvelles classes ont été ajoutées sous l'espace de noms SQLClient pour nous aider à migrer les données par lots via DataTable ou DataReader. La source de données peut provenir d'une base de données relationnelle ou d'un fichier XML, voire des résultats renvoyés par WebService. L'une des classes les plus importantes est la classe SqlBulkCopy, qui peut facilement nous aider à migrer les données de la source de données vers la base de données cible.
Illustrons d'abord l'utilisation de cette classe à travers un exemple simple :
DateHeure heure de début ;
protected void Button1_Click (expéditeur de l'objet, EventArgs e)
{
startTime = DateTime.Maintenant ;
chaîne SrcConString ;
chaîne DesConString ;
SqlConnection SrcCon = new SqlConnection();
SqlConnection DesCon = new SqlConnection();
SqlCommand SrcCom = new SqlCommand();
SqlDataAdapter SrcAdapter = new SqlDataAdapter();
DataTable dt = new DataTable();
SrcConString =
ConfigurationManager.ConnectionStrings["SrcDBConnectionString"].ConnectionString;
DesConString =
ConfigurationManager.ConnectionStrings["DesDBConnectionString"].ConnectionString;
SrcCon.ConnectionString = SrcConString ;
SrcCom.Connection = SrcCon;
SrcCom.CommandText = " SELECT * From [SrcTable]";
SrcCom.CommandType = CommandType.Text ;
SrcCom.Connection.Open();
SrcAdapter.SelectCommand = SrcCom;
SrcAdapter.Fill(dt);
SqlBulkCopy DesBulkOp ;
DesBulkOp = nouveau SqlBulkCopy(DesConString,
SqlBulkCopyOptions.UseInternalTransaction);
DesBulkOp.BulkCopyTimeout = 500000000 ;
DesBulkOp.SqlRowsCopié +=
nouveau SqlRowsCopiedEventHandler(OnRowsCopied);
DesBulkOp.NotifyAfter = dt.Rows.Count ;
essayer
{
DesBulkOp.DestinationTableName = "SrcTable";
DesBulkOp.WriteToServer(dt);
}
attraper (Exception ex)
{
lblResult.Text = ex.Message;
}
enfin
{
SrcCon.Close();
DesCon.Close();
}
}
private void OnRowsCopied (expéditeur de l'objet, arguments SqlRowsCopiedEventArgs)
{
lblCounter.Text += args.RowsCopied.ToString() + " les lignes sont copiées
";
TimeSpan copyTime = DateTime.Now - startTime ;
lblCounter.Text += "Durée de copie :" + copyTime.Seconds.ToString() + "." + copyTime.Milliseconds.ToString() + " secondes" ;
}
Analysez ensuite ces lignes de code en détail :
SqlBulkCopy DesBulkOp ;
DesBulkOp = new SqlBulkCopy(DesConString, SqlBulkCopyOptions.UseInternalTransaction); Générez d'abord une instance de SqlBulkCopy. Le constructeur spécifie la base de données cible. L'utilisation de SqlBulkCopyOptions.UseInternalTransaction signifie que l'action de migration est spécifiée dans une transaction. un retour en arrière se produira. Veuillez vous référer à MSDN pour d'autres options.
DesBulkOp.BulkCopyTimeout = 500000000 ;
Spécifiez le délai d'expiration pour l'achèvement de l'opération
DesBulkOp.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnRowsCopied);
DesBulkOp.NotifyAfter = dt.Rows.Count ;
essayer
{
DesBulkOp.DestinationTableName = "SrcTable";
DesBulkOp.WriteToServer(dt);
}
L'attribut NotifyAfter spécifie le nombre de lignes de données à traiter avant l'événement de notification. Ici, il est spécifié comme le nombre de lignes dans la table, et l'événement SqlRowsCopied est ajouté pour afficher l'heure de l'ensemble du processus de migration. La méthode WriteToServer copie la source de données dans la base de données cible. Avant d'utiliser la méthode WriteToServer, vous devez d'abord spécifier l'attribut DestinationTableName, qui est le nom de la table de la base de données cible.
Nous pouvons également définir nous-mêmes une Transaction, par exemple :
SqlTransaction Transaction ;
Transaction =
SrcCom.Connection.BeginTransaction();
SqlBulkCopy DesBulkOp ;
DesBulkOp = nouveau SqlBulkCopy (nouveau SqlConnection (DesConString),
SqlBulkCopyOptions.Default,
Transaction) ;
essayez
{
//..
}
attraper{}
enfin
{
Transaction.Commit();
}
Il existe également une classe SqlBulkCopyColumnMapping qui permet de mapper les champs de la source de données avec des champs nommés différemment dans les données cibles. Autrement dit, si les noms de colonnes des données cible et des données source sont différents, vous pouvez utiliser cette classe pour le mappage :
SqlBulkCopyColumnMapping ColMap = new SqlBulkCopyColumnMapping("SrcCol", "DesCol");
DesBulkOp.ColumnMappings.Add(ColMap);
Ou vous pouvez ajouter un mappage directement :
DesBulkOp.ColumnMappings.Add("SrcCol", "DesCol");
Problèmes de performances :
J'ai utilisé l'exemple ci-dessus pour tester et migrer environ 20 000 enregistrements. Cela a pris moins d'une seconde. Je dois dire que les performances sont toujours bonnes. De plus, en utilisant le profil SQL pour surveiller les événements de migration, vous pouvez constater qu'il existe très peu d'enregistrements de requête, seulement quelques-uns. On dit que l'utilisation de SqlBulkCopy peut réduire considérablement le temps de migration des données.