2016-08-04 3 views
1

У меня есть довольно много данных, которые могут быть загружены в базу данных Из-за большого размера одна таблица занимает 5 минут, чтобы завершить вставку. 2 стола у меня ушло 10 минутAsync для массовой копии

static void Main(string[] args) 
{ 
    DataTableBulkInsert(DataTable1); 
    DataTableBulkInsert(DataTable2); 
} 

public static void DataTableBulkInsert(DataTable Table){ 
    SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(myConnection); 
    sqlBulkCopy.DestinationTableName = "dbo.DatabaseTable"; 
    myConnection.Open();      
    sqlBulkCopy.WriteToServer(Table); 
    myConnection.Close(); 
} 

Я сейчас пытаюсь сделать асинхра для массовой вставки, но есть ни какие-либо данные не вставлены ни дают мне ошибку. Как зафиксировать исключение?

static void Main(string[] args) 
{ 
    var insert1 = Task.Run(async() => await DataTableBulkInsert(DataTable1); 
    var insert2 = Task.Run(async() => await DataTableBulkInsert(DataTable2); 
    Task.WhenAll(insert1, insert 2); 
} 

public static async Task<Boolean> DataTableBulkInsert(DataTable Table) 
{ 
     try 
     { 
      SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(myConnection); 
      sqlBulkCopy.DestinationTableName = "dbo.DatabaseTable"; 
      myConnection.Open();      
      await sqlBulkCopy.WriteToServerAsync(Table); 
      myConnection.Close(); 
     } 
     catch (Exception (e)) 
     { 
     console.write(e); 
     } 
     return true; 
} 
+0

Вы пытались настроить отладчик на строке 'console.write (e);'? В моем опыте методы async часто проглатывают исключения. – smoksnes

+3

Используйте 'Task.WaitAll (insert1, insert 2)' –

ответ

3

Task.Run s ничего не добавляет. Кроме того, не пытайтесь совместно использовать одно соединение объект между двумя запусками вашего метода. Что-то вроде:

static void Main(string[] args) 
{ 
    var insert1 = DataTableBulkInsert(DataTable1); 
    var insert2 = DataTableBulkInsert(DataTable2); 
    Task.WaitAll(insert1, insert2); 
} 

public static async Task DataTableBulkInsert(DataTable Table) 
{ 
     using(var localConnection = new SqlConnection(/* connection string */)) 
     { 
      SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(localConnection); 
      sqlBulkCopy.DestinationTableName = "dbo.DatabaseTable"; 
      localConnection.Open();      
      await sqlBulkCopy.WriteToServerAsync(Table); 
     } 
} 

Нормально return await является анти-модель, но здесь вы хотите использовать его таким образом, чтобы using заявление не закрывает соединение, пока после того, как основная нагрузка будет завершена.

Кроме того, я перешел на использование Task.WaitAll, который фактически ждет, что больше, чем при использовании идиоматических Task.WhenAll, а затем сразу же вызова Wait на него.

+0

_return await is anti-pattern_ - Очень интересно. Не могли бы вы предоставить дополнительную информацию об этом? – smoksnes

+1

@smoksnes - 'await' - способ приостановить текущий метод, пока какой-либо другой фрагмент кода не выполнит свою работу. Если все, что ваш метод будет делать, когда он будет возобновлен, должен сказать: «Я закончил», то почему вы пошли на все усилия? При этом фактический анти-шаблон является 'return await', если это * только *' await' в методе (как он есть здесь), и он не находится в блоке 'try' с' finally' или 'using 'block (в этом случае есть дополнительный код для запуска после' return') –

+1

@smoksnes - есть даже проблема [github] (https://github.com/dotnet/roslyn/issues/1981) с просьбой о компиляторе оптимизируйте его. –

0

Task.WhenAll возвращает объект Task, который должен быть ожидаемым или код, который следует продолжает свою нормальную работу, и основной метод выходит немедленно.

Поскольку это консольное приложение и главное не могут быть помечены как async, вы можете использовать это:

Task.WhenAll(insert1, insert2).Wait(); // wait for the returned Task object to Complete 

Нормальное использование является: await (Task.WhenAll(...)), но вы не можете пометить Main как async метод ,

+0

Он работает после того, как я добавил в .Wait(); Однако, теперь я получаю связь открытой и закрытой проблемой. Как разрешить одно соединение обслуживать множественную объемную копию? – Jonathan

+0

Просто попробовал и сделал это. – Jonathan

+0

@ Jonathan вам может понадобиться создать отдельное соединение для каждой задачи. или закройте соединение после строки 'Task.WhenAll (insert1, insert2) .Wait();'. – user3185569

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