-
Notifications
You must be signed in to change notification settings - Fork 286
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
SqlDataReader incorrectly returns null ROWVERSION as an empty byte[] #255
Comments
Apparently this issue was raised before in .NET Framework but not fixed because it would be a breaking change. Perhaps it can be fixed here, and left as-is in .NET Framework. |
Hi @dbrownems @davidbaxterbrowne With Microsoft.Data.SqlClient, we have some room for flexibility and we also support both .NET Framework and .NET Core. We may have room for the breaking fix in future (with a planned major bump with other breaking changes combined), only criteria is what's the impact of the issue and how would it affect existing behaviors or if it will cause any regressions. We can mark this issue as breaking behavior change that needs deep investigation and analyze it in depth when a major version release is planned. Does that sound fair? |
It does to me. This is a very uncommon scenario, as a ROWVERSION column in a table is never actually NULL. It's automatically populated on INSERT and can't be directly updated. The only scenario where you have a Null ROWVERSION is in a query result like in the attached SO issue. |
If we end up "fixing" this, then this should be done with an app context switch, so that an application that is migrating to Microsoft.Data.SqlClient on netfx, can switch to the old behavior, in case it is not possible to change the check for the migrating application. |
I was just working on fixing this. Question, should the AppContext switch default to the new behaviour (to return SqlBinary.Null) or the old behaviour? 3.0.0 will contain other breaking changes so I think it might be good to default to the new behaviour and have the switch return it to the old behaviour. Is that ok? |
I think this behavior is simply wrong, and should be changed by default. |
The changes would make it:
Trying to get SqlBinary Null on the reader test would be very difficult because it doesn't work in the same way as the parameter does. Anything which is null through the reader is going to return you a DBNull rather than the specific type. |
I'm not sure I follow this. As if I do the following I get back a using var cmd = new SqlCommand(@"select convert(binary(8),convert(timestamp, null))", conn);
using var reader = await cmd.ExecuteReaderAsync();
await reader.Read();
var type = reader.GetFieldType(0);
var value = reader.GetSqlValue(0); type is a |
Yes. Except you won't have to know to do that anymore which is the fix. |
I'm unclear what happened to this?
In the above code if tableA.fieldOne contain a value for 'HelloWorld' but tableB.fieldOne does not, then we expect to get back the fieldOne and fieldTwo from tableA and we expect to get back null and null for b.fieldOne and b.rowVersion. But currently b.rowVersion DOES NOT return null it returns 0x. If one tries to use |
The issue was closed by the changes in #998 and the behaviour changed. If you want the old behaviour you can use the compatibility context switch Are you saying that the change as discussed and approved/merged isn't not correct? or that you don't like the way the change works? |
I appreciate your work on this. I want the new (ie correct) behavior but am not currently experiencing it. I'm running Microsoft.Data.SqlClient 4.1 which must be before the fix. Which version contains the fix? Is there a NuGet package for it that I can use? |
It should be in all current versions, this is quite an old issue. Can you make your test sql into a small standalone c# test program and open a new issue with it please? that way it will get tracked correctly and be easier to reproduce and possibly fix. |
I just tested with the repro at the top of this issue. Using Microsoft.Data.SqlClient 4.1 the behavior is correct, the ROWVERSION is returned as Null. Using System.Data.SqlClient 4.8.3, the old behavior is the same, the ROWVERSION is returned as an empty byte[]. |
I'd probably need some help writing this up sufficiently and perhaps I'm barking up the wrong tree here but the issue I'm encountering smells very similar to the issue reported here. More specifically, instead of getting back a null as I expect for the joined
Running the above code produces these results: Notice in the results above that row 2 has a b_rowVersion value of |
That is a slightly weird behaviour. That value is null as far as sql is concerned, if you try to datalength or null check it you'll get consistent behaviour for a null value. You should not get an exception when asking for the value through GetSqlBinary Sql Management Studio uses this library so a change here would also affect it. It may be that management studio isn't prepared for the SqlBinary.Null value and doesn't check for IsNull instead just asks for the length and formats it. That would explain the display weirdness there. @DavoudEshtehari is there anyone on the management studio team we could ping on that? |
BTW |
SSMS uses System.Data.SqlClient. (Version 19 in preview uses M.D.S.) |
the SqlBinary crash or the 0x in management studio? |
Exactly. And I think you are being slightly kind :-)
Totally agree. Here another interesting thing about this case. Even though |
Opened #1684 to track it. |
When returned in a resultset a null ROWVERSION is returned as an empty byte[], instead of DbNull.Value. This problem does not occur when returning using a parameter value, or using a resultset in ODBC (so not a TDS issue).
Here's e a repro:
Expected behavior
SqlClient: AllowDbNull True IsDbNull: True DBNull
SqlClient (parameter): IsDbNull: True SqlBinary Null
ODBC: AllowDbNull True IsDbNull: True DBNull
Actual Behavior
SqlClient: AllowDbNull True IsDbNull: False Byte[] System.Byte[]
SqlClient (parameter): IsDbNull: True SqlBinary Null
ODBC: AllowDbNull True IsDbNull: True DBNull
The text was updated successfully, but these errors were encountered: