SqlDataAdapter.Fill - Asynchronous approach
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
SqlDataAdapter.Fill() is a synchronous method in ADO.NET that populates a DataTable or DataSet with query results. Unlike SqlCommand, SqlDataAdapter does not have a native async FillAsync() method. To avoid blocking threads (especially in ASP.NET or WPF applications), you need alternative approaches to perform the equivalent operation asynchronously.
The Problem: Synchronous Fill Blocks the Thread
In an ASP.NET request handler or WPF UI thread, this blocks the thread and reduces scalability or freezes the UI.
Approach 1: Use SqlDataReader with Async Methods
The recommended approach is to use SqlCommand.ExecuteReaderAsync() and manually load the data:
DataTable.Load() is synchronous but runs against an already-fetched reader. The network I/O (the slow part) is handled asynchronously by ExecuteReaderAsync().
Approach 2: Fully Async Row-by-Row Loading
For complete async control, read rows individually:
Or build the DataTable column by column:
Approach 3: Task.Run Wrapper (Not Recommended)
Wrapping the synchronous call in Task.Run offloads to a thread pool thread but does not provide true async I/O:
This is acceptable in desktop applications (WPF/WinForms) to unblock the UI thread, but is wasteful in ASP.NET where thread pool threads are precious.
Approach 4: Extension Method
Create a reusable async extension:
With Parameters
Dapper Alternative
Consider using Dapper for simpler async database access:
Dapper is fully async and maps results directly to objects, eliminating the need for DataTable in most cases.
Common Pitfalls
- Exception Handling: Asynchronous operations require conscious exception management; ensure proper try-catch blocks are incorporated, especially dealing with
SqlException. - Resource Management: Always utilize
usingorawait usingstatements to manageIDisposableresources efficiently to avoid memory leaks and connection pool exhaustion. - Configuration and Performance: Opt for configurations that support appropriate concurrent connections from the client side and manage connection pooling effectively.
- Task.Run in ASP.NET: Using
Task.Runto wrapFill()in ASP.NET wastes a thread pool thread on blocking I/O. UseExecuteReaderAsyncfor true async I/O. - DataTable.Load thread safety:
DataTableis not thread-safe. Do not share aDataTableacross multiple async operations without synchronization. - Connection lifetime: Keep connections open only as long as needed. Open with
OpenAsync, read data, then letusingdispose the connection.
Summary
SqlDataAdapter.Fill()has no native async version- Use
SqlCommand.ExecuteReaderAsync()+DataTable.Load(reader)for async filling - Avoid
Task.Runwrappers in ASP.NET — they waste thread pool threads - Create extension methods for reusable async fill patterns
- Consider Dapper for simpler async database access without
DataTable
Related reading
- SqlDateTime.MinValue DateTime.MinValue, why?
- sqlite3.ProgrammingError Incorrect number of bindings supplied. The current statement uses 1, and there are 74 supplied
- SQLite - ORDER BY RAND
- SQLite equivalent to ISNULL, NVL, IFNULL or COALESCE
- SQLite Sharing Connections across threads to read and write
- SslStream asynchronous methods always return an IAsyncResult where CompletedSynchronously is True. Why?
- SqlParameterCollection only accepts non-null SqlParameter type objects, not String objects
- Stack capacity in C

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.