Skip to content
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

Add GetFieldValue(Async)<T> support for XmlReader, TextReader, Stream #1019

Merged
merged 13 commits into from
Oct 6, 2021

Conversation

Wraith2
Copy link
Contributor

@Wraith2 Wraith2 commented Apr 2, 2021

Fixes: #27

Before M.D.SqlClient was created from the netfx and netcore versions of S.D.SqlClient i had added support for GetFieldValue<XmlReader> in netcore. This PR replaces that version of the code with a more appropriate version that correctly implements SequentialAccess behaviour (by returning a sequential reader immediately instad of buffering) and extends the support for GetFieldValue and it's async version to include Stream TextReader and XmlReader parameter types.

I had previously raised questions about what the null behaviour should be for these types. Currently the behaviour when requesting the value of a stream column which has a null value in the current row is that an empty object of the correct type will be returned. I think this behaviour is in place to make stream usage easier for consumers and have not changed it. If an error were thrown instead it would be more difficult to write a clear consumer of the api. The IsDbNull(async) will correctly return true for null row values.

It is not clear that this support is needed in netfx builds at this time. Eventually netcore and netfx codebases will be merged and all capabilities will be equal in all versions (depending on platform support), at that time this support will reach netfx. Porting this change to netfx is possible but time consuming due to the different implementations of async and the many small but important differences in core classes between the two.

All existing tests pass. New tests for the specific types (Stream, XmlReader, TextReader), their accessors (GetXmlReader, GetFieldValue<XmlReader>, GetFieldValueAsync<XmlReader> etc) and behaviours (Default, SequentialAccess) have been added. The new tests are in a new class because I found that the existing tests test many things in a single method making debugging them more difficult that I would like, the new tests are slightly less complex per test so it's clearer what aspect of behaviour has changed when they fail.

/cc @roji as requester, @ErikEJ as interested party

Copy link
Member

@DavoudEshtehari DavoudEshtehari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change needs to update docs and includes the new supported types with more samples. I'm not sure if it's going to be included with this PR or in a separate PR! My preference is to wrap it up here.

CC @cheenamalhotra

@Wraith2
Copy link
Contributor Author

Wraith2 commented Jun 24, 2021

I added the newly supported types to the tables for the two affected methods. The streaming docs were already linked so I don't think anything more is needed.

@DavoudEshtehari
Copy link
Member

DavoudEshtehari commented Jun 24, 2021

Greate!
Since those types are not fully supported in SqlClient with different frameworks, could you specify that(maybe adding in a Note box under the supported types table)? In addition, we'd better mention the empty object behavior as you've mentioned in your comment.

I had previously raised questions about what the null behaviour should be for these types. Currently the behaviour when requesting the value of a stream column which has a null value in the current row is that an empty object of the correct type will be returned. I think this behaviour is in place to make stream usage easier for consumers and have not changed it. If an error were thrown instead it would be more difficult to write a clear consumer of the api. The IsDbNull(async) will correctly return true for null row values.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Jun 24, 2021

Since those types are not fully supported by all frameworks,

They aren't? FileStreams aren't supported on unix but binary data in a database field is entirely supported, same with xml and text.

The null object behaviour is identical to that of GetXmlReader, GetTextReader and GetStream, we could link to those pages but i don't think I'd want to duplicate the docs for that.

@DavoudEshtehari
Copy link
Member

Updated that comment!

I meant they're not fully supported in SqlClient yet:

It is not clear that this support is needed in netfx builds at this time. Eventually netcore and netfx codebases will be merged and all capabilities will be equal in all versions (depending on platform support), at that time this support will reach netfx. Porting this change to netfx is possible but time consuming due to the different implementations of async and the many small but important differences in core classes between the two.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Jun 24, 2021

Oh, I see. That needs an official decision on whether this feature is wanted on netfx. If it is needed/wanted on netfx then it can probably be implemented as long as the changes in SqlDataReader are thoroughly reviewed, they're pretty low level which means if they're wrong there would be hard to reproduce errors.

@DavoudEshtehari DavoudEshtehari added ❔ Question Further information is requested 💡 Enhancement New feature request labels Jun 24, 2021
@Wraith2
Copy link
Contributor Author

Wraith2 commented Jul 18, 2021

@David-Engel @cheenamalhotra this is waiting on a decision on whether this functionality is needed in netfx.
The original request comes from EF Core which does not support netfx. The implementation detail is intricate and I feel that if it is needed in netfx i'd like to get it validated through review before I try to port it.

@cheenamalhotra
Copy link
Member

cheenamalhotra commented Jul 19, 2021

We need to keep NetFx and NetCore as much close to each other as possible to aid merging codebases. I agree there are differences in design, but if we don't port things over, we are increasing that gap even further and that increases possibility of issues when we do port them over later or someday merge these classes.

e.g. there were issues in PR #1084 that is not related to any of the changes that were made in the related PR in NetCore but it could have required thorough debugging and time investment to investigate failures to figure out why things weren't porting over successfully due to some other existing design gaps.

As we always give equal importance to NetFx for all the new features that are added to the driver, same should be done for anything else. Our ultimate goal is to merge these codebases, and so we need to give importance to maintain design parity as much as possible.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Jul 19, 2021

Ok, so netfx wanted. In which case I'll wait for review on the SqlDataReader changes which are the intricate part.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Aug 16, 2021

Any update on this? The further from doing the work it gets the less likely I am to be able to remember all the reasons for changes if they're not clear from the code.

@cheenamalhotra
Copy link
Member

@Wraith2 We'll start reviewing it soon, please resolve conflicts to prepare for review.
Thanks! :)

@Wraith2
Copy link
Contributor Author

Wraith2 commented Aug 24, 2021

Done, but as usual there wouldn't be conflicts to resolve if it hadn't been waiting here so long.

Copy link
Member

@cheenamalhotra cheenamalhotra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make changes for NetFx too, the changes in NetCore look good to me 👍🏻

@cheenamalhotra
Copy link
Member

Hi @roji

Just wanted to grab your attention on this PR, the changes look promising as per requested. Thanks to @Wraith2 :)
Let us know your feedback on the same. We're considering this support to be included in the next preview.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Sep 28, 2021

If you want it for the next preview what are the timescales on that? I've got a big rebase to do and then I've got to work these changes back into netfx which has some different parts since data reader isn't synced. Plus, you know, my day job.

@cheenamalhotra
Copy link
Member

cheenamalhotra commented Sep 29, 2021

Please ensure your branch has all updates from dotnet/main, we've stopped building with .NET Core 2.1 now - the PR was merged just yesterday. But if that's a warning, it doesn't mean anything, you can ignore it. You can compare output with some other test u know works, with the failing tests, because the tests hang up, so no output probably means there's a hung up test.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Sep 30, 2021

Fun. Nothing quite like debugging against a moving target. I've rebased and rebuilt now and I still get the same thing. Something in the tests is building against 2.1 and it's being inappropriately used in the net461 build.
Here's the build batch file, note that there's a clean at the start to make sure nothing gets used between different build targets.

@echo off

set netfx=net461
set config=Debug
set platform=AnyCpu

msbuild -t:clean
msbuild -p:BuildNetFx=true -p:Configuration=%config% -p:Platform=%platform%
msbuild -t:BuildTestsNetFx -p:TargetNetFxVersion=%netfx%

dotnet test "src\Microsoft.Data.SqlClient\tests\ManualTests\Microsoft.Data.SqlClient.ManualTesting.Tests.csproj" -p:Platform="%platform%" -p:Configuration="%config%" -p:TestTargetOS="Windowsnetfx" --no-build -v n --filter "GetFieldValueAsync_OfStream"

I've identified where the error is but as you hopefully remember it's slow going when you have to remote attach the debugger to the test to look at what's going on.

@cheenamalhotra
Copy link
Member

Just to let you know, there are quite many PRs queued today, so it builds may not run soon enough.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Sep 30, 2021

That's fine, I've got a local repro of the hang and haven't worked out the cause yet. i just pushed to make sure the rebase was done properly.

@Wraith2
Copy link
Contributor Author

Wraith2 commented Sep 30, 2021

Actually the message has now changed to use 3.1 and not 2.1, it's still an inappropriate dll to use though.

Test run detected DLL(s) which were built for different framework and platform versions. Following DLL(s) do not match current settings, which are .NETFramework,Version=v4.6.1 framework and X86 platform.
ManualTests.dll is built for Framework .NETCoreApp,Version=v3.1 and Platform AnyCPU.
Go to https://aka.ms/tp/vstest/multitargetingdoc?view=vs-2019 for more details on managing these settings.

DavoudEshtehari and others added 2 commits October 5, 2021 18:44
* Update DataReaderStreamsTest.cs to add Exception tests
# Conflicts:
#	src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj
@cheenamalhotra cheenamalhotra merged commit 3d73709 into dotnet:main Oct 6, 2021
@Wraith2
Copy link
Contributor Author

Wraith2 commented Oct 6, 2021

Woo!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💡 Enhancement New feature request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SqlDataReader.GetFieldValue{,Async}() should work for Stream and TextReader
4 participants