none
Insertar gran cantidad de registros contenidos en List <T> RRS feed

  • Pregunta

  • Hola...

    Tengo que insertar registros contenidos en una List<T> y esta es algo grande...mi pregunta es si se puede hacer con SqlBulkCopy y si es asi ...como seria el codigo??

    he visto ejemplos pero con archivos o de tabla a tabla ,,, pero no pasando un objeto de tipo lista ..


    EFRAIN MEJIAS C VALENCIA - VENEZUELA

    martes, 18 de junio de 2019 22:47

Respuestas

Todas las respuestas

  • hola

    >>insertar registros contenidos en una List<T> y esta es algo grande

    a que llamamos grande ? porque si hablamos de Gb de datos quizas debas tomar otra estrategia como seria ir volcando los datos a una queue y que un proceso separado los vaya procesando de a poco, o sea no seria un proceso online

    Podrias convertir la lista a DataTable usando el CopyToDataTable<> y luego esto con el SqlBulkCopy

    Crear un objeto DataTable a partir de una consulta (LINQ to DataSet)

    pero si de por si la lista es grande y debes generar un datatable que aun pesara mas quizas tengas problemas de memoria, pero bueno evalalo quizas puedas aplicarlo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    miércoles, 19 de junio de 2019 6:56
  • Hola, puedes crear un método de extensión para transformar una lista en un DataTable 

        public static class IEnumerableExtensions
        {
            public static DataTable AsDataTable<T>(this IEnumerable<T> data)
            {
                PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
                var table = new DataTable();
                foreach (PropertyDescriptor prop in properties)
                    table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
                foreach (T item in data)
                {
                    DataRow row = table.NewRow();
                    foreach (PropertyDescriptor prop in properties)
                        row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                    table.Rows.Add(row);
                }
                return table;
            }
        }

    Y luego aplicar lo siguiente (es un ejemplo)

     var listPerson = new List<Person>
         {
              new Person() {Id = 1}, 
              new Person() {Id = 2}
         };
    
     using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["SomeConnectionString"].ConnectionString))
         {
              connection.Open();
              SqlTransaction transaction = connection.BeginTransaction();
    
              using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transaction))
              {
                 bulkCopy.BatchSize = 100;
                 bulkCopy.DestinationTableName = "dbo.Person";
                 try
                 {
                     bulkCopy.WriteToServer(listPerson.AsDataTable());
                 }
                 catch (Exception)
                 {
                     transaction.Rollback();
                     connection.Close();
                 }
               }
    
               transaction.Commit();
         }


    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó, vótala como útil. Saludos

    • Propuesto como respuesta Carlos_Ruiz_M martes, 25 de junio de 2019 14:32
    miércoles, 19 de junio de 2019 9:17
    Moderador
  • Si son muchos datos, no te conviene dupliarlos en memoria como ocurre si usas la conversión a DataTable que te sugieren en las respuestas anteriores. En su lugar, puedes usar una sobrecarga del SqlBulkCopy que recibe un IDataReader como parámetro.

    Construir el IDataReader a partir del List<T> no es sencillo, pero afortunadamente hay gente que ya lo ha hecho, y puedes copiar su código. Por ejemplo, mira este post:

    https://stackoverflow.com/questions/2258310/get-an-idatareader-from-a-typed-list

    miércoles, 19 de junio de 2019 12:31
    Moderador