Inserción de datos con Bulk Copy a base de datos Sql Server 2019

Fecha de Publicación: 2021-04-30

Introducción

En este ejercicio insertaremos datos de forma masiva desde un archivo de texto a tabla de base de datos en Sql Server 2019.

Requisitos

  • Visual Studio 2019
  • Sql Server Management 2019
  • Archivo con datos para insertar, en este caso sera un archivo con datos de personas ya trabajado anteriormente



Resultado

La siguiente imagen muestra lo que obtendremos al realizar este ejercicio:





código Fuente

Descargar

Ejercicio

Tomaremos como base el ejercicio anterior donde abrimos y parseamos el archivo que contienen datos de las personas para enfocarnos en la inserción con este metodo, aca te dejo el link correspondiente para que puedas darle una revisada y si te sirve utilizar el código del mismo. Bien, como vemos en la imagen nuestro programa ya tiene un poco de código, el cual la declaración de variables para leer el archivo y hacerle su parsing, así que tomando como base esto procederemos al siguiente paso.



Agregaremos la referencia using System.Data.SqlClient; a nuestro programa.





Ahora agregaremos nuestra cadena de conexión en el App.config como se muestra en la figura. Te dejo el código a insertar a continuación:

  
'<'connectionStrings>
  '<'add providerName="System.Data.SqlClient" name="ConnString" connectionString="Server=.;Database=devel;User Id=sa;Password=12345;" />
'<'/connectionStrings>
  
  

Nota: Recuerda cambiar el User Id y el Password acorde a tu configuración.



Una vez configurada nuestra conexión en el App.config procederemos a agregarla en nuestro programa, declarando una variable tipo string y con la siguiente instrucción la traeremos del App.config:

  
strConnection = ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString;
  
  

En la imagen se muestra como quedaria con esta modificación:



Ahora si, viene lo interesante por hacer, declararemos un metodo que se llamara InsertPersonData al cual le pasaremos 2 parametros y nos regresara 1 de tipo int,el primero será la lista de datos tipo Person que ya trabajamos anteriormente y el segundo será la cadena de conexión que acabamos de configurar, el dato que nos regresara será un conteo de los datos insertados en la tabla en la base de datos, quedando de la siguiente forma:

  
  nCountRows = InsertPersonData(lst, strConnection);
  
  


Ahora comenzaremos a trabajar sobre el metodo InsertPersonData, comenzaremos por declarar nuestra variable de retorno la cual es un tipo int y la configuramos para que sea lo que regrese el metodo, así mismo un SqlCommand para manejar la conexión de la base de datos, quedando de la siguiente forma:

  
static public int InsertPersonData(List lst, string strConnection)
{
  SqlCommand sqlCommand = new SqlCommand();

  int nCountValues = 0;

  return nCountValues;
}
  
  


Bien, para poder trabajar con la clase SqlBulkCopy se tienen que realizar estos pasos:

  • Configurar una variable BulCopy con la cadena de conexión a la base de datos
  • Declarar la tabla destino (tabla donde se insertaran los datos)
  • Declarar un objeto DataTable con las columnas de la tabla destino (columnas que contiene la tabla donde se insertaran los datos)
  • Mapeo entre las columnas declaradas anteriormente y los nombres de los campos reales de la tabla en la base de datos
  • Iteración para llenar el objeto DataTable con los datos de la lista
  • Realizar la inserción a la tabla en la base de datos
Comenzaremos configurando una variable BulCopy con la cadena de conexión a la base de datos, insertaremos en nuestro código un try catch para tener mayor control si es que existe algun error, agregaremos en finally para cerrar siempre la conexión a la base de datos pase lo que pase:

  
try
{
    using (var bulkcopy = new SqlBulkCopy(strConnection))
    {

    }

    catch (Exception ex)
    {
       throw new Exception(ex.Message + " " + ex.StackTrace);
    }
    finally
    {
       sqlCommand.Connection.Close();
    }
}
  
  

Quedando de la siguiente forma nuestro metodo InsertPersonData:



El paso siguente es declarar la tabla destino (tabla donde se insertaran los datos), lo hacemos con el siguiente código:

  
bulkcopy.BatchSize = lst.Count;
bulkcopy.DestinationTableName = "Person";
bulkcopy.BulkCopyTimeout = 1800;//Media Hora
  
  

Donde el primer parametro es la cantidad de datos que contiene la lista, el segundo el nombre de la tabla y el tercero la cantidad de segundos a esperar para poder terminar la tarea completa.



Ahora declaramos el objeto tipo DataTable con los los nombres de las columnas de la tabla destino (se pueden ocupar otros nombres, pero para evitar confusiones de nombres despues yo lo utilizo así). El código es el siguiente:

  
//DataTable
DataTable destinationTable = new DataTable();
destinationTable.Columns.Add("firstName");
destinationTable.Columns.Add("lastName");
destinationTable.Columns.Add("gender");
destinationTable.Columns.Add("country");
destinationTable.Columns.Add("age");
destinationTable.Columns.Add("date");
destinationTable.Columns.Add("id");
  
  

Como se puede observar se agrega una columna del DataTable por cada campo de la tabla destino.



Ahora lo que haremos es mapear las columnas del DataTable y la tabla destino, esto lo realizaremos con el siguiente código, cabe señalar que por cada columna en la tabla destino, le corresponde un campo del DataTable.

  
//Mappings Columns
bulkcopy.ColumnMappings.Add("firstName", "firstName");
bulkcopy.ColumnMappings.Add("lastName", "lastName");
bulkcopy.ColumnMappings.Add("gender", "gender");
bulkcopy.ColumnMappings.Add("country", "country");
bulkcopy.ColumnMappings.Add("age", "age");
bulkcopy.ColumnMappings.Add("date", "date");
bulkcopy.ColumnMappings.Add("id", "id");
  
  

Y el metodo se ve así:



Ahora toca el turno a llenar el objeto DataTable con los datos que queremos insertar, eso lo realizamos con un foreach recorriendo la lista de tipo Person y eso lo realizamos con el siguiente código:

  
foreach (Person item in lst)
{
    destinationTable.Rows.Add(
        item.FirstName
       , item.LastName
       , item.Gender
       , item.Country
       , item.Age
       , item.Date
       , item.Id
       ); ;
}
  
  

Y así lo vamos viendo en nuestro metodo:



Bien ahora si, toca el turno a la instrucción que ejecuta lo anteriormente declarado y esa es:

  
bulkcopy.WriteToServer(destinationTable);
  
  

Esta ultima realizara el procedimiento de inserción de los datos en la base de datos, cabe mencionar que el tiempo de inserción dependera de la cantidad de datos a insertar aunque no debe demorar demasiado. En este caso es casi inmediato ya que son pocos registros (5000).
Así se ve el código dentro de nuestro metodo:



Con lo anterior hemos realizado la inserción con el metodo BulkCopy ahora lo que haremos será es una rapida comprobación de los datos insertados en la base y eso lo hacemos con el siguiente código:

  
sqlCommand.Connection = OpenDB(strConnection);
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText = "Select count(1) from Person;";

nCountValues = Convert.ToInt32(sqlCommand.ExecuteScalar());

sqlCommand.Connection.Close();
  
  

El cual como podemos obervar realiza un count a la tabla Person para corroborar cuantos datos fueron insertados.



Este código solo es para completar la unica llamada a OpenDB, no es necesaria para el BulkCopy.

  
static public SqlConnection OpenDB(string strConnection)
{
    SqlConnection sqlConn = new SqlConnection(strConnection);
    try
    {
        sqlConn.Open();
    }
    catch (SqlException ex)
    {
        throw new Exception(ex.Message, ex);
    }
    return sqlConn;
}
  
  


Bien, ya para finalizar nuestra programación nos regresamos a nuestro metodo Main e insertamos al final del metodo una linea que imprime en pantalla el numero de registros insertados en la base de datos.

  
  System.Console.Write("La cantidad de datos insertados es: " + nCountRows.ToString());
  
  


Y ejecutamos nuestro programa, deberemos de obtener una pantalla similar a esta:



Referencias