En .Net1.1, no es muy conveniente insertar por lotes todos los datos de toda la tabla de datos en la base de datos o migrar entre diferentes fuentes de datos. En .Net2.0, se agregaron varias clases nuevas bajo el espacio de nombres SQLClient para ayudarnos a migrar datos en lotes a través de DataTable o DataReader. La fuente de datos puede provenir de una base de datos relacional o un archivo XML, o incluso los resultados devueltos por WebService. Una de las clases más importantes es la clase SqlBulkCopy, que puede ayudarnos fácilmente a migrar datos desde el origen de datos a la base de datos de destino.
Primero ilustraremos el uso de esta clase con un ejemplo simple:
FechaHora hora de inicio;
Botón vacío protegido1_Click (remitente del objeto, EventArgs e)
{
horaInicio = FechaHora.Ahora;
cadena SrcConString;
cadena DesConString;
SqlConnection SrcCon = nueva SqlConnection();
SqlConnection DesCon = nueva SqlConnection();
SqlCommand SrcCom = nuevo SqlCommand();
SqlDataAdapter SrcAdapter = nuevo SqlDataAdapter();
Tabla de datos dt = nueva Tabla de datos();
SrcConString =
ConfigurationManager.ConnectionStrings["SrcDBConnectionString"].ConnectionString;
DesConString =
ConfigurationManager.ConnectionStrings["DesDBConnectionString"].ConnectionString;
SrcCon.ConnectionString = SrcConString;
SrcCom.Conexión = SrcCon;
SrcCom.CommandText = " SELECCIONAR * De [SrcTable]";
SrcCom.CommandType = CommandType.Text;
SrcCom.Conexión.Open();
SrcAdapter.SelectCommand = SrcCom;
SrcAdapter.Fill(dt);
SqlBulkCopy DesBulkOp;
DesBulkOp = nuevo SqlBulkCopy(DesConString,
SqlBulkCopyOptions.UseInternalTransaction);
DesBulkOp.BulkCopyTimeout = 500000000;
DesBulkOp.SqlRowsCopied +=
nuevo SqlRowsCopiedEventHandler (OnRowsCopied);
DesBulkOp.NotifyAfter = dt.Rows.Count;
intentar
{
DesBulkOp.DestinationTableName = "SrcTable";
DesBulkOp.WriteToServer(dt);
}
captura (Excepción ex)
{
lblResult.Text = ex.Mensaje;
}
finalmente
{
SrcCon.Close();
DesCon.Close();
}
}
privado vacío OnRowsCopied (remitente del objeto, argumentos SqlRowsCopiedEventArgs)
{
lblCounter.Text += args.RowsCopied.ToString() + "las filas se copian<Br>";
TimeSpan copyTime = DateTime.Now - hora de inicio;
lblCounter.Text += "Tiempo de copia:" + copyTime.Seconds.ToString() + "." + copyTime.Millisegundos.ToString() + "segundos";
}
Luego analice estas líneas de código en detalle:
SqlBulkCopy DesBulkOp;
DesBulkOp = new SqlBulkCopy(DesConString, SqlBulkCopyOptions.UseInternalTransaction); primero genere una instancia de SqlBulkCopy. Si se produce un error o una excepción durante la migración de datos, se producirá una reversión. Consulte MSDN para conocer otras opciones.
DesBulkOp.BulkCopyTimeout = 500000000;
Especifique el tiempo de espera para completar la operación
DesBulkOp.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnRowsCopied);
DesBulkOp.NotifyAfter = dt.Rows.Count;
intentar
{
DesBulkOp.DestinationTableName = "SrcTable";
DesBulkOp.WriteToServer(dt);
}
El atributo NotifyAfter especifica la cantidad de filas de datos que se procesarán antes del evento de notificación. Aquí, se especifica como la cantidad de filas en la tabla y se agrega el evento SqlRowsCopied para generar la hora de todo el proceso de migración. El método WriteToServer copia la fuente de datos a la base de datos de destino. Antes de utilizar el método WriteToServer, primero debe especificar el atributo DestinationTableName, que es el nombre de la tabla de la base de datos de destino.
También podemos definir una Transacción nosotros mismos, por ejemplo:
SqlTransaction Transaction;
Transacción =
SrcCom.Connection.BeginTransaction();
SqlBulkCopy DesBulkOp;
DesBulkOp = nuevo SqlBulkCopy(nuevo SqlConnection(DesConString),
SqlBulkCopyOptions.Default,
transacción);
intentar
{
//..
}
atrapar{}
finalmente
{
Transacción.Commit();
}
También hay una clase SqlBulkCopyColumnMapping que permite asignar campos de origen de datos a campos con nombres diferentes en los datos de destino. Es decir, si los nombres de las columnas de los datos de destino y los datos de origen son diferentes, puede utilizar esta clase para el mapeo:
SqlBulkCopyColumnMapping ColMap = nuevo SqlBulkCopyColumnMapping("SrcCol", "DesCol");
DesBulkOp.ColumnMappings.Add(ColMap);
O puedes agregar mapeo directamente:
DesBulkOp.ColumnMappings.Add("SrcCol", "DesCol");
Problemas de rendimiento:
Utilicé el ejemplo anterior para probar y migrar unos 20.000 registros. Me llevó menos de un segundo. Debo decir que el rendimiento sigue siendo bueno. Además, al utilizar el perfil SQL para monitorear eventos de migración, puede ver que hay muy pocos registros de solicitudes, solo unos pocos. Se dice que utilizar SqlBulkCopy puede reducir en gran medida el tiempo de migración de datos.