Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9007057

Browse files
authored
Merge pull request #34880 from Wraith2/sqlfeature-getfieldvaluexml
SqlClient enhancement enable GetFieldValue<XmlReader>
2 parents da8f7ea + eeb6139 commit 9007057

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

src/System.Data.SqlClient/src/System/Data/SqlClient/SqlDataReader.cs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,10 +2588,10 @@ private T GetFieldValueFromSqlBufferInternal<T>(SqlBuffer data, _SqlMetaData met
25882588
// If its a SQL Type or Nullable UDT
25892589
object rawValue = GetSqlValueFromSqlBufferInternal(data, metaData);
25902590

2591-
// Special case: User wants SqlString, but we have a SqlXml
2592-
// SqlXml can not be typecast into a SqlString, but we need to support SqlString on XML Types - so do a manual conversion
25932591
if (typeofT == s_typeofSqlString)
25942592
{
2593+
// Special case: User wants SqlString, but we have a SqlXml
2594+
// SqlXml can not be typecast into a SqlString, but we need to support SqlString on XML Types - so do a manual conversion
25952595
SqlXml xmlValue = rawValue as SqlXml;
25962596
if (xmlValue != null)
25972597
{
@@ -2610,22 +2610,58 @@ private T GetFieldValueFromSqlBufferInternal<T>(SqlBuffer data, _SqlMetaData met
26102610
}
26112611
else
26122612
{
2613-
// Otherwise Its a CLR or non-Nullable UDT
2614-
try
2613+
if (typeof(XmlReader) == typeofT)
26152614
{
2616-
return (T)GetValueFromSqlBufferInternal(data, metaData);
2615+
if (metaData.metaType.SqlDbType != SqlDbType.Xml)
2616+
{
2617+
throw SQL.XmlReaderNotSupportOnColumnType(metaData.column);
2618+
}
2619+
else
2620+
{
2621+
object clrValue = null;
2622+
if (!data.IsNull)
2623+
{
2624+
clrValue = GetValueFromSqlBufferInternal(data, metaData);
2625+
}
2626+
if (clrValue is null) // covers IsNull and when there is data which is present but is a clr null somehow
2627+
{
2628+
return (T)(object)SqlTypeWorkarounds.SqlXmlCreateSqlXmlReader(
2629+
new MemoryStream(Array.Empty<byte>(), writable: false),
2630+
closeInput: true
2631+
);
2632+
}
2633+
else if (clrValue.GetType() == typeof(string))
2634+
{
2635+
return (T)(object)SqlTypeWorkarounds.SqlXmlCreateSqlXmlReader(
2636+
new StringReader(clrValue as string),
2637+
closeInput: true
2638+
);
2639+
}
2640+
else
2641+
{
2642+
// try the type cast to throw the invalid cast exception and inform the user what types they're trying to use and that why it is wrong
2643+
return (T)clrValue;
2644+
}
2645+
}
26172646
}
2618-
catch (InvalidCastException)
2647+
else
26192648
{
2620-
if (data.IsNull)
2649+
try
26212650
{
2622-
// If the value was actually null, then we should throw a SqlNullValue instead
2623-
throw SQL.SqlNullValue();
2651+
return (T)GetValueFromSqlBufferInternal(data, metaData);
26242652
}
2625-
else
2653+
catch (InvalidCastException)
26262654
{
2627-
// Legitimate InvalidCast, rethrow
2628-
throw;
2655+
if (data.IsNull)
2656+
{
2657+
// If the value was actually null, then we should throw a SqlNullValue instead
2658+
throw SQL.SqlNullValue();
2659+
}
2660+
else
2661+
{
2662+
// Legitimate InvalidCast, rethrow
2663+
throw;
2664+
}
26292665
}
26302666
}
26312667
}

src/System.Data.SqlClient/src/System/Data/SqlTypes/SqlTypeWorkarounds.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ internal static XmlReader SqlXmlCreateSqlXmlReader(Stream stream, bool closeInpu
3737

3838
return XmlReader.Create(stream, settingsToUse);
3939
}
40+
41+
internal static XmlReader SqlXmlCreateSqlXmlReader(TextReader textReader, bool closeInput = false, bool async = false)
42+
{
43+
Debug.Assert(closeInput || !async, "Currently we do not have pre-created settings for !closeInput+async");
44+
45+
XmlReaderSettings settingsToUse = closeInput ?
46+
(async ? s_defaultXmlReaderSettingsAsyncCloseInput : s_defaultXmlReaderSettingsCloseInput) :
47+
s_defaultXmlReaderSettings;
48+
49+
return XmlReader.Create(textReader, settingsToUse);
50+
}
4051
#endregion
4152

4253
#region Work around inability to access SqlDateTime.ToDateTime

src/System.Data.SqlClient/tests/ManualTests/SQL/DataStreamTest/DataStreamTest.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ private static void GetValueOfTRead(string connectionString)
294294
rdr.GetFieldValue<SqlXml>(15);
295295
rdr.GetFieldValue<SqlString>(14);
296296
rdr.GetFieldValue<SqlString>(15);
297+
rdr.GetFieldValue<XmlReader>(14);
298+
rdr.GetFieldValue<XmlReader>(15);
299+
rdr.GetFieldValueAsync<XmlReader>(14);
300+
rdr.GetFieldValueAsync<XmlReader>(15);
297301

298302
rdr.Read();
299303
Assert.True(rdr.IsDBNullAsync(11).Result, "FAILED: IsDBNull was false for a null value");

0 commit comments

Comments
 (0)