1+ // Licensed to the .NET Foundation under one or more agreements.
2+ // The .NET Foundation licenses this file to you under the MIT license.
3+ // See the LICENSE file in the project root for more information.
4+
5+ using System . Data . SqlTypes ;
6+ using System . Runtime . InteropServices ;
7+
8+ namespace Microsoft . Data . SqlTypes
9+ {
10+ /// <summary>
11+ /// This type provides workarounds for the separation between System.Data.Common
12+ /// and Microsoft.Data.SqlClient. The latter wants to access internal members of the former, and
13+ /// this class provides ways to do that. We must review and update this implementation any time the
14+ /// implementation of the corresponding types in System.Data.Common change.
15+ /// </summary>
16+ internal static partial class SqlTypeWorkarounds
17+ {
18+ #region Work around inability to access SqlMoney.ctor(long, int) and SqlMoney.ToSqlInternalRepresentation
19+ /// <summary>
20+ /// Constructs a SqlMoney from a long value without scaling. The ignored parameter exists
21+ /// only to distinguish this constructor from the constructor that takes a long.
22+ /// Used only internally.
23+ /// </summary>
24+ internal static SqlMoney SqlMoneyCtor ( long value , int ignored )
25+ {
26+ var c = default ( SqlMoneyCaster ) ;
27+
28+ // Same behavior as the internal SqlMoney.ctor(long, bool) overload
29+ c . Fake . _fNotNull = true ;
30+ c . Fake . _value = value ;
31+
32+ return c . Real ;
33+ }
34+
35+ internal static long SqlMoneyToSqlInternalRepresentation ( SqlMoney money )
36+ {
37+ var c = default ( SqlMoneyCaster ) ;
38+ c . Real = money ;
39+
40+ // Same implementation as the internal SqlMoney.ToSqlInternalRepresentation implementation
41+ if ( money . IsNull )
42+ {
43+ throw new SqlNullValueException ( ) ;
44+ }
45+ return c . Fake . _value ;
46+ }
47+
48+ [ StructLayout ( LayoutKind . Sequential ) ]
49+ private struct SqlMoneyLookalike // exact same shape as SqlMoney, but with accessible fields
50+ {
51+ internal bool _fNotNull ;
52+ internal long _value ;
53+ }
54+
55+ [ StructLayout ( LayoutKind . Explicit ) ]
56+ private struct SqlMoneyCaster
57+ {
58+ [ FieldOffset ( 0 ) ]
59+ internal SqlMoney Real ;
60+ [ FieldOffset ( 0 ) ]
61+ internal SqlMoneyLookalike Fake ;
62+ }
63+ #endregion
64+
65+ #region Work around inability to access SqlDecimal._data1/2/3/4
66+ internal static void SqlDecimalExtractData ( SqlDecimal d , out uint data1 , out uint data2 , out uint data3 , out uint data4 )
67+ {
68+ // Extract the four data elements from SqlDecimal.
69+ var c = default ( SqlDecimalCaster ) ;
70+ c . Real = d ;
71+ data1 = c . Fake . _data1 ;
72+ data2 = c . Fake . _data2 ;
73+ data3 = c . Fake . _data3 ;
74+ data4 = c . Fake . _data4 ;
75+ }
76+
77+ [ StructLayout ( LayoutKind . Sequential ) ]
78+ private struct SqlDecimalLookalike // exact same shape as SqlDecimal, but with accessible fields
79+ {
80+ internal byte _bStatus ;
81+ internal byte _bLen ;
82+ internal byte _bPrec ;
83+ internal byte _bScale ;
84+ internal uint _data1 ;
85+ internal uint _data2 ;
86+ internal uint _data3 ;
87+ internal uint _data4 ;
88+ }
89+
90+ [ StructLayout ( LayoutKind . Explicit ) ]
91+ private struct SqlDecimalCaster
92+ {
93+ [ FieldOffset ( 0 ) ]
94+ internal SqlDecimal Real ;
95+ [ FieldOffset ( 0 ) ]
96+ internal SqlDecimalLookalike Fake ;
97+ }
98+ #endregion
99+
100+ #region Work around inability to access SqlBinary.ctor(byte[], bool)
101+ internal static SqlBinary SqlBinaryCtor ( byte [ ] value , bool ignored )
102+ {
103+ // Construct a SqlBinary without allocating/copying the byte[]. This provides
104+ // the same behavior as SqlBinary.ctor(byte[], bool).
105+ var c = default ( SqlBinaryCaster ) ;
106+ c . Fake . _value = value ;
107+ return c . Real ;
108+ }
109+
110+ [ StructLayout ( LayoutKind . Sequential ) ]
111+ private struct SqlBinaryLookalike
112+ {
113+ internal byte [ ] _value ;
114+ }
115+
116+ [ StructLayout ( LayoutKind . Explicit ) ]
117+ private struct SqlBinaryCaster
118+ {
119+ [ FieldOffset ( 0 ) ]
120+ internal SqlBinary Real ;
121+ [ FieldOffset ( 0 ) ]
122+ internal SqlBinaryLookalike Fake ;
123+ }
124+ #endregion
125+
126+ #region Work around inability to access SqlGuid.ctor(byte[], bool)
127+ internal static SqlGuid SqlGuidCtor ( byte [ ] value , bool ignored )
128+ {
129+ // Construct a SqlGuid without allocating/copying the byte[]. This provides
130+ // the same behavior as SqlGuid.ctor(byte[], bool).
131+ var c = default ( SqlGuidCaster ) ;
132+ c . Fake . _value = value ;
133+ return c . Real ;
134+ }
135+
136+ [ StructLayout ( LayoutKind . Sequential ) ]
137+ private struct SqlGuidLookalike
138+ {
139+ internal byte [ ] _value ;
140+ }
141+
142+ [ StructLayout ( LayoutKind . Explicit ) ]
143+ private struct SqlGuidCaster
144+ {
145+ [ FieldOffset ( 0 ) ]
146+ internal SqlGuid Real ;
147+ [ FieldOffset ( 0 ) ]
148+ internal SqlGuidLookalike Fake ;
149+ }
150+ #endregion
151+ }
152+ }
0 commit comments