Преобразуйте IEnumerable в DataTable и пытался сделать что-то подобное, создавая метод расширения. Я задаю свой вопрос, поскольку проблема, с которой я столкнулся, может заключаться где-то еще.
По сути, у меня довольно большой IEnumerable (около 16–17 миллионов элементов) до этого момента у меня не было никаких проблем с этим, пока я не попробовал преобразовать это в DataTable, используя метод расширения:
Код: Выделить всё
///
/// Converts IEnumerable to datatable. Mainly for use when using SQLBulkCopy/>
///
///
///
/// Custom order for columns allows me to make sure that the order of columns will always be the same. Am open for suggestions for better ways to do this
///
public static DataTable ToDataTable(this IEnumerable collection, List customColumnOrder)
{
DataTable dt = new DataTable();
var type = collection.First().GetType();
foreach (var column in customColumnOrder)
{
dt.Columns.Add(column.Item1, Nullable.GetUnderlyingType(type.GetProperty(column.Item1).PropertyType) ?? type.GetProperty(column.Item1).PropertyType);
}
// Populate the table
foreach (T item in collection)
{
DataRow dr = dt.NewRow();
dr.BeginEdit();
foreach (var column in customColumnOrder)
{
dr[column.Item1] = type.GetProperty(column.Item1).GetValue(item) ?? DBNull.Value;
}
dr.EndEdit();
dt.Rows.Add(dr);
}
return dt;
}
Я конвертирую в DataTable поэтому я могу использовать SqlBulkCopy для передачи данных в базу данных.
EDIT: отсюда передаются данные
Код: Выделить всё
///
/// SqlBulkCopy for saving large amounts of data
///
///
///
/// Custom manager to use alongside the model
/// Connection string to DB
public void BatchSave(IEnumerable dataToSave, IData modelManager, string conn)
{
var model = dataToSave.First();
using (SqlConnection sqlconn= new SqlConnection(conn))
{
sqlconn.Open();
using (SqlCommand cmd = new SqlCommand(GetCreateScript(modelManager, model), sqlconn))
{
//Create temp table to do initial insert into
cmd.ExecuteNonQuery();
SqlBulkCopy copy = new SqlBulkCopy(cmd.Connection);
copy.DestinationTableName = "#tempTableForImport";
// Convert data to DataTable
DataTable dt = dataToSave.ToDataTable(modelManager.GetDataColumnsOrder());
// Copy to temp table
copy.WriteToServer(dt);
}
using (SqlCommand cmd = new SqlCommand(modelManager.GetInsertSproc(), sqlconn) { CommandType=CommandType.StoredProcedure })
{
// Clean up data and move to final table
cmd.ExecuteNonQuery();
}
sqlconn.Close();
}
}
Код: Выделить всё
public void BatchSave(IEnumerable dataToSave, IData modelManager, string conn)
{
var model = dataToSave.First();
using (SqlConnection sqlconn = new SqlConnection(conn))
{
sqlconn.Open();
using (var bcp = new SqlBulkCopy(sqlconn))
{
using (var reader = ObjectReader.Create(dataToSave, modelManager.GetDataColumnsOrder().Select(s => s.Item1).ToArray() /*modelManager.GetDataColumnsOrder().Select(obj=>obj.Item1).ToString()*/))
{
using (SqlCommand cmd = new SqlCommand(GetCreateScript(modelManager, model), sqlconn))
{
cmd.ExecuteNonQuery();
bcp.DestinationTableName = "#tempTableForImport";
bcp.WriteToServer(reader);
}
using (SqlCommand cmd = new SqlCommand(modelManager.GetInsertSproc(), sqlconn) { CommandType = CommandType.StoredProcedure })
{
cmd.ExecuteNonQuery();
}
}
}
sqlconn.Close();
}
}
Спасибо всем за помощь, прошло примерно 30 секунд, есть еще идеи по этому поводу? Может быть, как-нибудь увеличить время до тайм-аута?
Подробнее здесь: https://stackoverflow.com/questions/329 ... -datatable
Мобильная версия