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