-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider adding FillAsync and async APIs on data adapters #22109
Comments
Moving to future because of lack of resources |
Alternatively if someone from the community would like to drive this, the effort would be welcome. |
This needs a formal API proposal written up. @spudcud do you want to do this - updating your top post is clearest? |
Not sure if this helps, but someone has implemented this. https://github.com/voloda/AsyncDataAdapter/blob/master/AsyncDataAdapter/DataAdapter.cs |
@danmosemsft any chance this can be added to Core 3.0? |
+1 on this, |
@danmosemsft @saurabh500 any updates on this? |
+1 |
Moving to out of System.Data.SqlClient and into System.Data because I believe the methods should be added to the base DbDataAdapter, before any provider implements it. I am also keeping this issue in the Future milestone because we need a much better understanding of its impact before we decide to pick it up and implement it in a specific release. For example:
On the flip side, If someone from the community wanted to drive this, I believe the API design part, and possibly the implementation of FillAsync on SqlClient, would be relatively simple. The job is mostly to duplicate the code of the sync version into async methods, and also make sure that all potentially blocking calls in the implementation use async APIs as well. For the SqlCient implementation of Update, currently batching is internal and synchronous. I suspect it would make sense to leverage the new public batching APIs from https://github.com/dotnet/corefx/issues/35135 once they are in place. |
cc @roji @ajcvickers |
Similar to dotnet/corefx#35012, which adds missing async APIs elsewhere in ADO.NET. Adding these APIs in the System.Data base classes is probably easy enough (with them delegating by default to the sync APIs, as usual with ADO.NET), allowing providers to implement later. |
Would it help if I publish a PR for that? It seems pretty straightforward. Effy |
Is this still under review? |
@uprightbass360 this issue is currently in the backlog, which means we don't have immediate plans to implement it priority-wise. In general, investment in DbDataAdapter is mostly limited to maintenance at this point, but given enough user feedback we would definitely consider it. This could be a good issue for the community to look into. |
@maxle5 you added this feature to your fork. Any chance to create a PR? |
One small note - I haven't reviewed @maxle5's commit, but we'd want to add async across all operations performed by DbDataAdapter, and not just for some (FillAsync). We don't want to end up with a type that only partially supports async. |
@roji I think @maxle5's commit creates all the necessary methods: |
In that case a PR would be good to have! |
@roji, we don't accept PRs for new APIs until those APIs have been reviewed and approved. Have these? I don't see a formal API proposal here. Thanks. |
@stephentoub this is only about adding async counterparts to already-existing sync APIs on DbDataAdapter. But you're right of course... @maxle5, what we'd need is an list of public APIs being added. |
Full list of public APIs that were added (async counterparts to already-existing sync APIs): namespace System.Data.Common
{
public partial class DataAdapter
{
public virtual Task<int> FillAsync(DataSet dataSet);
protected virtual Task<int> FillAsync(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords);
protected virtual Task<int> FillAsync(DataTable dataTable, IDataReader dataReader);
protected virtual Task<int> FillAsync(DataTable[] dataTables, IDataReader dataReader, int startRecord, int maxRecords);
public virtual Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType);
protected virtual Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, string srcTable, IDataReader dataReader);
protected virtual Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, IDataReader dataReader);
}
public partial class DbDataAdapter
{
public override Task<int> FillAsync(DataSet dataSet);
public Task<int> FillAsync(DataSet dataSet, int startRecord, int maxRecords, string srcTable);
protected virtual Task<int> FillAsync(DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior);
public Task<int> FillAsync(DataSet dataSet, string srcTable);
public Task<int> FillAsync(DataTable dataTable);
protected virtual Task<int> FillAsync(DataTable dataTable, IDbCommand command, CommandBehavior behavior);
protected virtual Task<int> FillAsync(DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior);
public Task<int> FillAsync(int startRecord, int maxRecords, params DataTable[] dataTables);
public override Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType);
protected virtual Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior);
public Task<DataTable[]> FillSchemaAsync(DataSet dataSet, SchemaType schemaType, string srcTable);
public Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType);
protected virtual Task<DataTable> FillSchemaAsync(DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior);
}
public partial interface IDbDataAdapter
{
Task PrepareAsync(CancellationToken cancellationToken);
Task<int> ExecuteNonQueryAsync();
Task<IDataReader> ExecuteReaderAsync();
Task<IDataReader> ExecuteReaderAsync(CommandBehavior behavior);
Task<object> ExecuteScalarAsync();
}
public partial interface IDbDataAdapter
{
Task CloseAsync();
Task OpenAsync(CancellationToken cancellationToken);
}
} |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@roji any updates? |
Just bumping myself (sorry!) for awareness: For those wanting something in the meanwhile, my |
+1 for async version of |
Any update on this? |
So... Maybe .NET8? |
@ChristineBoersen I've created a very-very basic solution for my problem, which is similar to yours: I just need to fill an empty DataSet with data from an already opened DataReader. You can create your own version based on this. The main differences from your requirements:
public static async Task FillAsync(this DataSet dataSet, DbDataReader dataReader, CancellationToken cancellationToken)
{
var dataTable = dataSet.Tables.Add("Table");
for (int i = 0; i < dataReader.FieldCount; i++)
{
var column = new DataColumn(dataReader.GetName(i), dataReader.GetFieldType(i));
dataTable.Columns.Add(column);
}
var values = new object[dataTable.Columns.Count];
dataTable.BeginLoadData();
while (await dataReader.ReadAsync(cancellationToken))
{
dataReader.GetValues(values);
dataTable.LoadDataRow(values, true);
}
dataTable.EndLoadData();
} |
+1 async |
@roji You wrote:
It is two years later. Could we please get an answer on the DIM? |
This comment was marked as duplicate.
This comment was marked as duplicate.
2 similar comments
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
+1 async |
.net9 pretty please. |
Definitely need this for cases where EF Core is not good enough for maintaining SLA and have to end up using Stored Procedure with multiple datasets. |
@Tasin5541 and others, I recommend taking a look at Dapper. |
Like what? Non ORM direct SQL. |
Sorry for messaging at the thread, it's possible of reviewing this PR again with a API proposal? This issue seems very critical to me, there is no way to populate a DataTable completely asynchronously or any way to work with dynamic runtime data at EF Core. Any chance for .NET 10? |
Core 2.0 preview 1 now supports SqlDataAdapter and DataTable which is great and the best way to fill a DataSet from a stored procedure is by using SqlDataAdapter.Fill(DataSet). This works perfectly when not used in an async environment. There is currently no way in Core or full .NET to do a FillAsync. Without a FillAsync which would take a single line of code now requires 20 lines of much more complicated code including using SqlDataReader.GetSchemaTable() which is currently broken preview 1. Based on other posts I believe it will be working in Preview 2 but have not seen a definitive on that.
This is not something for 2.0 but is a clear deficiency in truly being able to support a fully async back-end and would be a much needed improvement moving forward.
The text was updated successfully, but these errors were encountered: