Inserción de datos masivos en Oracle desde C#

Una tarea comun en el desarrollo de software es la insercion de datos a una Base de Datos, lo normal es hacerlo haciendo una llamada de inserción por cada registro que se tenga, sin embargo esto funciona para cantidades de datos pequeñas, ya que no se siente el tiempo de ejecucion, al contrario cuando se tiene cantidades de datos masivos, es necesario hacerlo de otra manera para mejorar el rendimiento y el tiempo de ejecución.

En esta entrada intentaré explicar como insertar datos masivos de manera eficiente, usando la clausula FOR ALL en oracle para procesar datos de forma masiva.

Empezamos creando una tabla en Oracle

CREATE TABLE ESQUEMA_DB.EMPLEADO
(
  EMPLEADO_ID              NUMBER                    NOT NULL,
  NOMBRES         VARCHAR2(250 BYTE)        NOT NULL,
  IDENTIFICACION  VARCHAR2(50 BYTE)         NOT NULL
)

El siguiente paso es crear un paquete oracle, y dentro de este crear tipos definidos, y un procedimiento para la inserción de datos:

Especificación Paquete Oracle

CREATE OR REPLACE PACKAGE ESQUEMA_DB.PKG_EMPLEADO AS
type t_emp_id is table of EMPLEADO.EMPLEADO_ID%type index by pls_integer;
type t_identificacion is table of EMP.IDENTIFICACION%type index by pls_integer;
type t_nombres is table of EMPLEADO.NOMBRES%type index by pls_integer;

PROCEDURE INSERTAR_EMPLEADOS(ID_IN IN t_emp_id, IDENTIFICACION_IN IN t_identificacion, NOMBRES_IN IN t_nombres , FilasAfectadas OUT NUMBER);
END PKG_EMPLEADO;
/

Cuerpo Paquete Oracle

CREATE OR REPLACE PACKAGE ESQUEMA_DB.PKG_EMPLEADO AS
PROCEDURE INSERTAR_EMPLEADOS(ID_IN IN t_emp_id, IDENTIFICACION_IN IN t_identificacion, NOMBRES_IN IN t_nombres , FilasAfectadas OUT NUMBER)
IS
BEGIN
  FORALL idx IN ID_IN.FIRST..ID_IN.LAST
    INSERT INTO EMPLEADO EMP (EMP.EMPLEADO_ID, EMP.NOMBRES, EMP.IDENTIFICACION)
    VALUES (ID_IN(idx), NOMBRES_IN(idx), IDENTIFICACION_IN(idx));
  FilasAfectadas:= SQL%RowCount;
  COMMIT;
END INSERTAR_EMPLEADOS;
END PKG_EMPLEADO;
/

Luego en C# creamos un modelo empleado:

public class Empleado
{
  public int ID {get; set;}
  public string Identificacion{get; set;}
  public string Nombres{get; set;}
}

Luego creamos el metodo que hará la insercion a la BD, enviando una lista de empleados:

public static int InsertarEmpleados(List < Empleado > empleados) {
 int resultado = 0;

 OracleConnection con = getConexion();
 con.Open();
 Console.WriteLine("Conectado a Oracle " + con.ServerVersion);

 OracleCommand cmd = con.CreateCommand();

 cmd.CommandText = "PKG_EMPLEADO.INSERTAR_EMPLEADOS";
 cmd.CommandType = CommandType.StoredProcedure;

 OracleParameter par;

 par = new OracleParameter();
 par.ParameterName = "ID_IN";
 par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
 par.OracleDbType = OracleDbType.Int32;
 par.Value = empleados.Select(x => x.ID).ToList().ToArray();
 cmd.Parameters.Add(par);

 par = new OracleParameter();
 par.ParameterName = "IDENTIFICACION_IN";
 par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
 par.OracleDbType = OracleDbType.Varchar2;
 par.Value = empleados.Select(x => x.Identificacion).ToList().ToArray();
 cmd.Parameters.Add(par);

 par = new OracleParameter();
 par.ParameterName = "NOMBRES_IN";
 par.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
 par.OracleDbType = OracleDbType.Varchar2;
 par.Value = empleados.Select(x => x.Nombres).ToList().ToArray();
 cmd.Parameters.Add(par);

 par = new OracleParameter();
 par.ParameterName = "FilasAfectadas";
 par.OracleDbType = OracleDbType.Int32;
 par.Direction = ParameterDirection.Output;
 cmd.Parameters.Add(par);

 cmd.FetchSize = cmd.FetchSize * 100;

 cmd.ExecuteNonQuery();

 int aux = Convert.ToInt32(cmd.Parameters["FilasAfectadas"].Value.ToString());

 if (!aux.Equals(0)) {
  resultado = aux;
 }

 con.Close();
 con.Dispose();

 return resultado;
}

El metodo anterior devuelve un int para saber el numero total de registros insertados en BD

Para saber un poco mas del tema de insercion de datos masivos se puede revisar el siguiente link: https://blogs.oracle.com/oraclemagazine/bulk-processing-with-bulk-collect-and-forall

Entradas creadas 12

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Publicaciones relacionadas

Comienza escribiendo tu búsqueda y pulsa enter para buscar. Presiona ESC para cancelar.

Volver arriba