2013-05-30 1 views
1

У меня есть модель и список экземпляров (около 5000), которые мне нужно скопировать в базу данных.Лучший способ конвертировать IEnumerable <T> в Datatable для SQL Bulk Copy

Я пытаюсь ассимилировать свои объекты в DataTable, но я не знаю, как это сделать:

public class BookingType { 

    public int ID { get; set; } 
    public string Name { get; set; } 
    public decimal Price { get; set; } 
    public int RandomProperty { get; set; } 
    public int RandomProperty2 { get; set; } 

} 

public void InsertSomeStuff(IEnumerable<BookingType> bookings) { 
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString)) { 
     conn.Open(); 

     DataTable dt = new DataTable(); 

     using (SqlBulkCopy copy = new SqlBulkCopy(conn)) { 
      copy.ColumnMappings.Add(0, 1); 

      copy.DestinationTableName = "dbo.Bookings"; 
      copy.WriteToServer(dt); 
     } 
    } 
} 

Как это сделать?

+1

Вы можете использовать общий метод [показанный здесь] (http://msdn.microsoft.com/en-us/library/bb669096.aspx) для создания datatable, заданный 'IEnumerable' любого произвольного типа. – Servy

ответ

4

Вы используете linq для sql? В этом случае, этот подход очень сладкий: Using SQL bulk copy with your LINQ-to-SQL datacontext

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

    public void BulkInsertAll<T>(IEnumerable<T> entities) 
    { 
     entities = entities.ToArray(); 

     string cs = Connection.ConnectionString; 
     var conn = new SqlConnection(cs); 
     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 => GetPropertyValue(
       property.GetValue(entity, null))).ToArray()); 
     } 

     bulkCopy.WriteToServer(table); 
     conn.Close(); 
    } 

    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; 
    } 

    private object GetPropertyValue(object o) 
    { 
     if (o == null) 
      return DBNull.Value; 
     return o; 
    } 
} 
+0

Будет ли это работать при той же производительности, что и Bulk to SQL? У меня есть ответ? (да, я использую L2S) – Smithy

+0

Я считаю, что код работает, но я получаю: данное значение типа DateTime из источника данных не может быть преобразовано в тип int указанного столбца цели. – Smithy

+0

Я предполагаю, что вы используете некоторые специальные сопоставления столбцов, но это довольно сложно сказать, не зная, как ваш класс сопоставляется с sql. –

Смежные вопросы