2012-02-10 22 views
13

Tengo una consulta que tiene el siguiente aspecto:inserción masiva con linq-to-sql

using (MyDC TheDC = new MyDC()) 
{ 
    foreach (MyObject TheObject in TheListOfMyObjects) 
    { 
     DBTable TheTable = new DBTable(); 

     TheTable.Prop1 = TheObject.Prop1; 
     ..... 
     TheDC.DBTables.InsertOnSubmit(TheTable); 

    } 
    TheDC.SubmitChanges(); 
} 

Esta consulta básicamente inserta una lista en la base de datos utilizando LINQ a SQL. Ahora he leído en línea que L2S NO admite operaciones masivas. ¿Funciona mi consulta insertando cada elemento a la vez o todos en una sola escritura?

Gracias por la aclaración.

Respuesta

7

El término Bulk Insert generalmente se refiere a la implementación de SQL Server específica ultra rápida basada en bcp SqlBulkCopy. Está construido en la parte superior de IRowsetFastLoad.

Linq-2-SQL no implementa inserción utilizando este mecanismo, bajo condiciones.

Si necesita cargar datos a gran escala en SQL Server y necesita que sean rápidos, le recomendaría la codificación manual mediante SqlBulkCopy.

LINQ-2-SQL intentará realizar algunas optimizaciones para acelerar múltiples inserciones, sin embargo, todavía no alcanzará muchos ORM micro (a pesar de que no hay ORM micro yo sepa aplicar SqlBulkCopy)

3

Generará una sola instrucción de inserción para cada registro, pero las enviará todas al servidor en un solo lote y se ejecutará en una sola transacción.

Eso es lo que hace SubmitChanges() fuera del bucle.

Si lo movió adentro, entonces cada iteración a través del lazo se iría al servidor para el INSERT y se ejecutaría en su propia transacción.

No creo que haya ninguna forma de desencadenar un SQL BULK INSERT.

+0

http://stackoverflow.com/a/1329094/17174 no han probado L2 insertar Potencia contra apuesto por un tiempo, pero lo hice ef prueba vs apuesto ... con resultados bastante decepcionantes para ef https://gist.github.com/1623514 –

26

que modificó el código del siguiente enlace para ser más eficiente y lo usé en mi aplicación. Es bastante conveniente porque puedes ponerlo en una clase parcial encima de tu clase autogenerada actual. En lugar de InsertOnSubmit agregue entidades a una lista, y en lugar de SubmitChanges llame al YourDataContext.BulkInsertAll(list).

http://www.codeproject.com/Tips/297582/Using-bulk-insert-with-your-linq-to-sql-datacontex

partial void OnCreated() 
{ 
    CommandTimeout = 5 * 60; 
} 

public void BulkInsertAll<T>(IEnumerable<T> entities) 
{       
    using(var conn = new SqlConnection(Connection.ConnectionString)) 
    { 
     conn.Open(); 

     Type t = typeof(T); 

     var tableAttribute = (TableAttribute)t.GetCustomAttributes(
      typeof(TableAttribute), false).Single(); 
     var bulkCopy = new SqlBulkCopy(conn) 
     { 
      DestinationTableName = tableAttribute.Name 
     }; 

     var properties = t.GetProperties().Where(EventTypeFilter).ToArray(); 
     var table = new DataTable(); 

     foreach (var property in properties) 
     { 
      Type propertyType = property.PropertyType; 
      if (propertyType.IsGenericType && 
       propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
      { 
       propertyType = Nullable.GetUnderlyingType(propertyType); 
      } 

      table.Columns.Add(new DataColumn(property.Name, propertyType)); 
     } 

     foreach (var entity in entities) 
     { 
      table.Rows.Add(
       properties.Select(
       property => property.GetValue(entity, null) ?? DBNull.Value 
       ).ToArray()); 
     } 

     bulkCopy.WriteToServer(table); 
    }            
} 

private bool EventTypeFilter(System.Reflection.PropertyInfo p) 
{ 
    var attribute = Attribute.GetCustomAttribute(p, 
     typeof(AssociationAttribute)) as AssociationAttribute; 

    if (attribute == null) return true; 
    if (attribute.IsForeignKey == false) return true; 

    return false; 
} 
+0

Usando Linqpad tuve que 't.GetProperties(). Where (EventTypeFilter)' to 't.GetFields()'. ¡Insertó 200k filas en poco más y un minuto! (y) –

+0

No se puede votar lo suficiente. Mi inserción de prueba de 212 registros estaba tomando 50s, esto lo cortó a 1.3s. ¡Debería ayudar cuando en realidad inserte 10k registros! – Ian

+0

mira esto: https://stackoverflow.com/a/21382542/1246870 - funcionó bien para mí – avs099

Cuestiones relacionadas