-
Notifications
You must be signed in to change notification settings - Fork 299
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
Retry not working with SqlDataAdapter.Fill(table) (.net framework) #1591
Comments
@MichaelAzzer we will look at it and will get back to you. |
Hi, is there a sample project that I can use to reproduce this? |
Yes, I prepared a simple sample to produce the problem this zipped file contains WinForms sample with database script.sql |
Thanks @MichaelAzzer , I was able to reproduce it locally with your sample project. I'll take a look and debug it. |
|
Hi @MichaelAzzer , I noticed that the exception being thrown is a timeout exception:
I change the Can you try changing the command timeout to a longer duration and try again and let me know if it works? |
Yes, you're right
|
Thanks for the clarification. I understand the issue now i.e. it's not triggering the retry callback from the |
After reading the implementation of SqlCommand.ExecuteReader(), I see that there's logic that checks if a RetryLogicProvider is provided in the SqlCommand and if so, the SqlReader returned is wrapped with RetryLogicProvider; however, in the core3.1 implementation of DbDataAdapter.FillInternal where the SqlDataAdapter inherits from, it grabs an IDataReader from ICommand.ExecuteReader. I think the issue is usage of the |
I appreciate this hard work, and I want to thank 😊 you very much |
You're welcome. After checking in with @DavoudEshtehari , he mentioned that the implementation was there since the repo was created, and the reason why we had to new was because ExecuteReader in DbCommand was not |
Note that ExecuteReader in DbCommand (and implements the IDbCommand.ExecuteReader discussed above) simply calls ExecuteDbDataReader, which is itself abstract. In other words, IDbCommand.ExecuteReader should indeed return an instance of SqlDataReader. (Providers are expected to indeed replace ExecuteReader with Note also that DbDataAdapter in general is a layer on top of DbCommand and DbDataReader, so at least in principle whatever works in a DbCommand implementation should also work via DbDataAdapter. There may be some additional complexity in SqlClient specifically that makes this difficult though - I'm not familiar with the internals. |
Sorry ,I have two more questions |
For your first question, since this behaviour was identified in your sample project, which is a .NET Framework 4.8 WinForms desktop application and DbDataAdapter from .NET Framework and DbDataAdapter from .NET Core 3.1 are nearly the same, I think the behaviour is consistent for both .NET Core and .NET Framework. As for you second question, here's my assumption and it does not reflect the actual decision on whether it'll be fixed or kept as it is. I think might be possible to fix it if we make SqlCommand inherit directly from ICommand instead of DbCommand to enable the RetryLogicProvider; however, there's a high probability that SqlCommand depends on logic from DbCommand and it may introduce some side effects that we may not expect, which is hopefully why we have unit tests, so I feel like the fix is risky, so the safer option is to say it's a limitation in Microsoft.Data.SqlClient and update the documentation, but any of the maintainers can chime in to this discussion. |
@David-Engel Can you please check this and guide us to the next step? |
We found that the
and updating your sample code to this
and I got it to trigger the Hence, there are 2 approaches to add
In that case, I'll remove my PR to update the docs. @JRahnama @David-Engel what do you think? |
@lcheunglci It's very nice 👌 to hear that I will try this solution |
hiding is not recommended. Net6 will give us CA1061 if we hide the method and it is suggested not to suppress this rule. Although we have couple of them inside the driver in SqlTransaction. |
I haven't been following this in detail, but FWIW hiding base methods - so as to return the more specific provider type - is a pretty standard part of how the ADO.NET API is designed: it allows for a form of covariance. For example, DbCommand has a protected abstract ExecuteDbDataReader method, as well as a public non-virtual ExecuteReader which calls the former. Both methods are typed to return DbDataReader. Now, an ADO.NET provider must override ExecuteDbDataReader with its implementation, which will return a provider-specific implementation of DbDataReader (e.g. SqlDataReader). But the public user AIP - ExecuteReader - still returns DbDataReader, meaning that users can't access any provider-specific APIs. So the provider hides ExecuteReader with its own version, which returns the specific type (SqlDataReader), allowing users to automatically get access to provider-specific features without downcasting etc. (again, I have no idea how any of this is related to retries - just commenting on the method hiding part!) |
When use retry with command and execute command with DataReader
like
it's working
but if I used SqlDataAdapter to fill table it's not working
The text was updated successfully, but these errors were encountered: