2017-07-14 101 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