2017-07-14 132 views
0

我正在爲我的WebAPI項目中使用的所有SQL基類添加異步實現。我對TAP範例相當陌生,所以我仍然在學習。異步填充C#數據表

我知道,由於其他職位,產生一個線程通過Task.Run()在ASP.NET上下文中沒有任何性能優勢。所以我對我的實現非常小心。

我已將我的QueryExecutor方法更改爲下面的異步實現。但無法弄清楚加載DataTable的最佳方式是什麼。我猜我最好想使用reader.ReadAsync()填充DataTable,但似乎在.NET 4.5框架中沒有任何東西可用。

所以我想問問是否值得寫我自己的擴展方法,如DataTable.LoadAsync(DbDataReader reader)?我有點不願意,如果它可以得到幫助,因爲它不會像管理.Net代碼那麼簡單。

讓我知道你們的想法。

private async Task<DataTable> ExecuteQueryInternalAsync(string commandText, CommandType commandType, SqlConnection sqlConnection, SqlTransaction transaction, params SqlParameter[] parameters) 
{ 
    using (SqlCommand cmd = new SqlCommand(commandText, sqlConnection) { CommandType = commandType, CommandTimeout = this.config.MainConnectionTimeoutInSeconds }) 
    { 
     if (transaction != null) 
      cmd.Transaction = transaction; 

     if (parameters != null) 
     { 
      foreach (var parameter in parameters) 
      { 
       if (parameter != null) 
       { 
        if (parameter.Value == null) 
         parameter.Value = DBNull.Value; 

        cmd.Parameters.Add(parameter); 
       } 
      } 
     } 

     if (sqlConnection.State == ConnectionState.Closed) 
      await sqlConnection.OpenAsync(); 

     using (var reader = await cmd.ExecuteReaderAsync()) 
     { 
      //Want to use: reader.ReadAsync() 
      var tb = new DataTable(); 
      tb.Load(reader); 
      return tb; 
     } 
    } 
} 

感謝, 保羅

+0

只是sidenode:您的示例代碼是受管理的.Net代碼 –

+0

通常,異步代碼使用Entit y框架查詢而不是'DataTable's。 –

+0

我確實使用EF 6.但是有時候您只需要執行一個SP並將結果作爲DataTable使用。 – Sal

回答

0

如果你想擴展方法,你可以在命令直接寫

public static class extensions 
    { 
     public async static Task<DataTable> ExecuteAndCreateDataTableAsync(this SqlCommand cmd) 
     { 
      using (var reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) 
      { 
       var dataTable = reader.CreateTableSchema(); 
       while (await reader.ReadAsync().ConfigureAwait(false)) 
       { 
        var dataRow = dataTable.NewRow(); 
        for (int i = 0; i < dataTable.Columns.Count; i++) 
        { 
         dataRow[i] = reader[i]; 
        } 
        dataTable.Rows.Add(dataRow); 
       } 
       return dataTable; 

      } 
     } 
     public static void LoadParams(this SqlCommand cmd, params SqlParameter[] parameters) 
     { 
      if (parameters != null) 
      { 
       foreach (var parameter in parameters) 
       { 
        if (parameter != null) 
        { 
         if (parameter.Value == null) 
          parameter.Value = DBNull.Value; 

         cmd.Parameters.Add(parameter); 
        } 
       } 
      } 
     } 


     private static DataTable CreateTableSchema(this SqlDataReader reader) 
     { 
      DataTable schema = reader.GetSchemaTable(); 
      DataTable dataTable = new DataTable(); 
      if (schema != null) 
      { 
       foreach (DataRow drow in schema.Rows) 
       { 
        string columnName = System.Convert.ToString(drow["ColumnName"]); 
        DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"])); 
        dataTable.Columns.Add(column); 
       } 
      } 
      return dataTable; 
     } 
    } 

和你medhod:

private async Task<DataTable> ExecuteQueryInternalAsync(string commandText, CommandType commandType, SqlConnection sqlConnection, SqlTransaction transaction, params SqlParameter[] parameters) 
     { 
      using (SqlCommand cmd = new SqlCommand(commandText, sqlConnection) { CommandType = commandType, CommandTimeout = this.config.MainConnectionTimeoutInSeconds }) 
      { 
       if (transaction != null) 
        cmd.Transaction = transaction; 

       cmd.LoadParams(parameters); 

       if (sqlConnection.State == ConnectionState.Closed) 
        await sqlConnection.OpenAsync(); 

       var datatable = await cmd.ExecuteAndCreateDataTableAsync(); 
       return datatable; 
      } 
     } 
+0

所以我的問題的一部分是,值得這樣做嗎?值得使用ReadAsync()而不是僅僅同步填充DataTable。 – Sal

+0

這只是實現。我認爲在ExecuteReaderAsync之後這是不必要的 – levent