Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data / Microsoft / SqlServer / Server / ValueUtilsSmi.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ValueUtilsSmi.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
8
9 namespace Microsoft.SqlServer.Server {
10
11     using System;
12     using System.Collections;
13     using System.Collections.Generic;
14     using System.Data;
15     using System.Data.Sql;
16     using System.Data.Common;
17     using System.Data.SqlClient;
18     using System.Data.SqlTypes;
19     using System.Diagnostics;
20     using System.Globalization;
21     using System.IO;
22     using System.Reflection;
23     using System.Xml;
24
25
26     // Utilities for manipulating values with the Smi interface.
27     //
28     //  THIS CLASS IS BUILT ON TOP OF THE SMI INTERFACE -- SMI SHOULD NOT DEPEND ON IT!
29     //
30     //  These are all based off of knowing the clr type of the value
31     //  as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible).
32     internal static class ValueUtilsSmi {
33         const int __maxByteChunkSize = TdsEnums.MAXSIZE;
34         const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char);        
35         const int NoLengthLimit = (int)SmiMetaData.UnlimitedMaxLengthIndicator;  // make sure we use the same constant
36
37         // Constants
38         const int constBinBufferSize = 4096;  // Size of the buffer used to read input parameter of type Stream
39         const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader       
40
41     //
42     //  User-visible semantics-laden Getter/Setter support methods
43     //      These methods implement common semantics for getters & setters
44     //      All access to underlying Smi getters/setters must validate parameters
45     //      in these methods
46     //  
47
48         //  The idea for the getters is that there are two types associated with the field/column,
49         //  the one the user asks for (implicitly via a strongly-typed getter) and the one the data 
50         //  is stored in (SmiMetaData).
51         //  When a strong getter is invoked, we try one of two ways to get the value
52         //      1) go directly to the source for the requested type if possible
53         //      2) instantiate the value based on the stored type (GetValue), then ask the Clr 
54         //          to convert.
55         internal static bool IsDBNull( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
56             return IsDBNull_Unchecked( sink, getters, ordinal );
57         }
58
59         internal static bool GetBoolean( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
60             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
61             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Boolean ) ) {
62                 return GetBoolean_Unchecked( sink, getters, ordinal );
63             }
64
65             object result = GetValue( sink, getters, ordinal, metaData, null  );
66             if (null == result) {
67                 throw ADP.InvalidCast();
68             }
69             return (Boolean)result;
70         }
71
72         internal static byte GetByte( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
73             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
74             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Byte ) ) {
75                 return GetByte_Unchecked( sink, getters, ordinal );
76             }
77             object result = GetValue( sink, getters, ordinal, metaData, null );
78             if (null == result) {
79                 throw ADP.InvalidCast();
80             }
81             return (Byte)result;
82         }
83
84         private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) {
85             object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
86             if (null == obj) {
87                 throw ADP.InvalidCast();
88             }
89             SqlBinary value = (SqlBinary) obj;
90
91             if (value.IsNull) {
92                 if (throwOnNull) {
93                     throw SQL.SqlNullValue();
94                 }
95                 else {
96                     // return zero length in any case
97                     return 0;
98                 }
99             }
100
101             if ( null == buffer ) {
102                 return value.Length;
103             }
104
105             length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, 
106                         fieldOffset, buffer.Length, bufferOffset, length );
107             Array.Copy( value.Value, checked((int)fieldOffset), buffer, bufferOffset, length );
108             return length;
109         }
110
111         internal static long GetBytes( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiExtendedMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull ) {
112             // Additional exclusions not caught by GetBytesInternal
113             if ( (SmiMetaData.UnlimitedMaxLengthIndicator != metaData.MaxLength &&
114                     (SqlDbType.VarChar == metaData.SqlDbType ||
115                      SqlDbType.NVarChar == metaData.SqlDbType ||
116                      SqlDbType.Char == metaData.SqlDbType ||
117                      SqlDbType.NChar == metaData.SqlDbType)) ||
118                     SqlDbType.Xml == metaData.SqlDbType) {
119                 throw SQL.NonBlobColumn(metaData.Name);
120             }
121             else {
122                 return GetBytesInternal(sink, getters, ordinal, metaData, fieldOffset, buffer, bufferOffset, length, throwOnNull);
123             }
124         }
125
126         internal static long GetBytesInternal( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull ) {
127             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.ByteArray ) ) {
128                 if (IsDBNull_Unchecked( sink, getters, ordinal )) {
129                     if (throwOnNull) {
130                         throw SQL.SqlNullValue();
131                     }
132                     else {
133                         // check user's parameters for validity against a zero-length value
134                         CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, 0, fieldOffset, buffer.Length, bufferOffset, length );
135
136                         // return zero length in any case
137                         return 0;
138                     }
139                 }
140                 long actualLength = GetBytesLength_Unchecked( sink, getters, ordinal );
141                 if ( null == buffer ) {
142                     return actualLength;
143                 }
144                 if (MetaDataUtilsSmi.IsCharOrXmlType(metaData.SqlDbType)) {
145                     length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength * sizeof(char), actualLength, 
146                                 fieldOffset, buffer.Length, bufferOffset, length );
147                 }
148                 else {
149                     length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, actualLength, fieldOffset, buffer.Length, bufferOffset, length );
150                 }
151                 Debug.Assert( length >= 0, "Invalid CheckXetParameters return length!" );
152                 if (length > 0) {
153                     length = GetBytes_Unchecked( sink, getters, ordinal, fieldOffset, buffer, bufferOffset, length);
154                 }
155                 return length;
156             }
157
158             return GetBytesConversion(sink, getters, ordinal, metaData, fieldOffset, buffer, bufferOffset, length, throwOnNull);
159         }
160         
161         internal static long GetChars( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, char[] buffer, int bufferOffset, int length ) {
162             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
163             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.CharArray ) ) {
164                 long actualLength = GetCharsLength_Unchecked( sink, getters, ordinal );
165                 if ( null == buffer ) {
166                     return actualLength;
167                 }
168                 length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, actualLength, fieldOffset, buffer.Length, bufferOffset, length );
169                 Debug.Assert( length >= 0, "Buffer.Length was invalid!" );
170                 if (length > 0) {
171                     length = GetChars_Unchecked( sink, getters, ordinal, fieldOffset, buffer, bufferOffset, length);
172                 }
173                 return length;
174             }
175
176             String value = ( (String) GetValue( sink, getters, ordinal, metaData, null  ) );
177             if (null == value) {
178                 throw ADP.InvalidCast();
179             }
180             if ( null == buffer ) {
181                 return value.Length;
182             }
183             length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, 
184                         fieldOffset, buffer.Length, bufferOffset, length );
185             value.CopyTo( checked((int)fieldOffset), buffer, bufferOffset, length );
186             return length;
187         }
188
189         internal static DateTime GetDateTime( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
190             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
191             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.DateTime ) ) {
192                 return GetDateTime_Unchecked( sink, getters, ordinal );
193             }
194             object result = GetValue( sink, getters, ordinal, metaData, null  );
195             if (null == result) {
196                 throw ADP.InvalidCast();
197             }
198             return (DateTime) result;
199         }
200
201         // calling GetDateTimeOffset on possibly v100 SMI
202         internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) {
203             if (gettersSupportKatmaiDateTime) {
204                 return GetDateTimeOffset(sink, (SmiTypedGetterSetter)getters, ordinal, metaData);
205             }
206             ThrowIfITypedGettersIsNull(sink, getters, ordinal);
207             object result = GetValue(sink, getters, ordinal, metaData, null);
208             if (null == result) {
209                 throw ADP.InvalidCast();
210             }
211             return (DateTimeOffset)result;
212         }
213
214         // dealing with v200 SMI
215         internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) {
216             ThrowIfITypedGettersIsNull(sink, getters, ordinal);
217             if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.DateTimeOffset)) {
218                 return GetDateTimeOffset_Unchecked(sink, getters, ordinal);
219             }
220             return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData, null);
221         }
222
223         internal static Decimal GetDecimal( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
224             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
225             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Decimal ) ) {
226                 return GetDecimal_PossiblyMoney( sink, getters, ordinal, metaData );
227             }
228             object result = GetValue( sink, getters, ordinal, metaData, null  );
229             if (null == result) {
230                 throw ADP.InvalidCast();
231             }
232             return (Decimal) result;
233         }
234
235         internal static Double GetDouble( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
236             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
237             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Double ) ) {
238                 return GetDouble_Unchecked( sink, getters, ordinal );
239             }
240             object result = GetValue( sink, getters, ordinal, metaData, null  );
241             if (null == result) {
242                 throw ADP.InvalidCast();
243             }
244             return (Double) result;
245         }
246
247         internal static Guid GetGuid( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
248             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
249             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Guid ) ) {
250                 return GetGuid_Unchecked( sink, getters, ordinal );
251             }
252             object result = GetValue( sink, getters, ordinal, metaData, null  );
253             if (null == result) {
254                 throw ADP.InvalidCast();
255             }
256             return (Guid) result;
257         }
258
259         internal static Int16 GetInt16( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
260             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
261             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Int16 ) ) {
262                 return GetInt16_Unchecked( sink, getters, ordinal );
263             }
264             object obj = GetValue( sink, getters, ordinal, metaData, null  );
265             if (null == obj) {
266                 throw ADP.InvalidCast();
267             }
268             return (Int16) obj;
269         }
270
271         internal static Int32 GetInt32( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
272             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
273             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Int32 ) ) {
274                 return GetInt32_Unchecked( sink, getters, ordinal );
275             }
276             object result = GetValue( sink, getters, ordinal, metaData, null  );
277             if (null == result) {
278                 throw ADP.InvalidCast();
279             }
280             return (Int32) result;
281         }
282
283         internal static Int64 GetInt64( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
284             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
285             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Int64 ) ) {
286                 return GetInt64_Unchecked( sink, getters, ordinal );
287             }
288             object result = GetValue( sink, getters, ordinal, metaData, null  );
289             if (null == result) {
290                 throw ADP.InvalidCast();
291             }
292             return (Int64) result;
293         }
294
295         internal static Single GetSingle( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
296             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
297             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Single ) ) {
298                 return GetSingle_Unchecked( sink, getters, ordinal );
299             }
300             object result = GetValue( sink, getters, ordinal, metaData, null  );
301             if (null == result) {
302                 throw ADP.InvalidCast();
303             }
304             return (Single) result;
305         }
306
307         internal static SqlBinary GetSqlBinary( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
308             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlBinary ) ) {
309                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
310                     return SqlBinary.Null;
311                 }
312                 return GetSqlBinary_Unchecked( sink, getters, ordinal );
313             }
314             object result = GetSqlValue( sink, getters, ordinal, metaData, null  );
315             if (null == result) {
316                 throw ADP.InvalidCast();
317             }
318             return (SqlBinary) result;
319         }
320
321         internal static SqlBoolean GetSqlBoolean( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
322             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlBoolean ) ) {
323                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
324                     return SqlBoolean.Null;
325                 }
326                 return new SqlBoolean( GetBoolean_Unchecked( sink, getters, ordinal ) );
327             }
328             object result = GetSqlValue( sink, getters, ordinal, metaData, null  );
329             if (null == result) {
330                 throw ADP.InvalidCast();
331             }
332             return (SqlBoolean) result;
333         }
334
335         internal static SqlByte GetSqlByte( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
336             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlByte ) ) {
337                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
338                     return SqlByte.Null;
339                 }
340                 return new SqlByte( GetByte_Unchecked( sink, getters, ordinal ) );
341             }
342             object result = GetSqlValue( sink, getters, ordinal, metaData, null  );
343             if (null == result) {
344                 throw ADP.InvalidCast();
345             }
346             return (SqlByte) result;
347         }
348
349         internal static SqlBytes GetSqlBytes( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context ) {
350             SqlBytes result;
351             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlBytes ) ) {
352                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
353                     result = SqlBytes.Null;
354                 }
355                 else {
356                     long length = GetBytesLength_Unchecked( sink, getters, ordinal );
357                     if ( 0 <= length && length < __maxByteChunkSize ) {
358                         byte[] byteBuffer = GetByteArray_Unchecked( sink, getters, ordinal );
359                         result = new SqlBytes( byteBuffer );
360                     }
361                     else {
362                         Stream s = new SmiGettersStream( sink, getters, ordinal, metaData );
363                         s = CopyIntoNewSmiScratchStream( s, sink, context );
364                         result = new SqlBytes( s );
365                     }
366                 }
367             }
368             else {
369                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
370                 if (null == obj) {
371                     throw ADP.InvalidCast();
372                 }
373                 SqlBinary binaryVal = (SqlBinary) obj;
374                 if ( binaryVal.IsNull ) {
375                     result = SqlBytes.Null;
376                 }
377                 else {
378                     result = new SqlBytes( binaryVal.Value );
379                 }
380             }
381
382             return result;
383         }
384
385         internal static SqlChars GetSqlChars( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context ) {
386             SqlChars result;
387             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlChars ) ) {
388                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
389                     result = SqlChars.Null;
390                 }
391                 else {
392                     long length = GetCharsLength_Unchecked( sink, getters, ordinal );
393                     if ( length < __maxCharChunkSize || !InOutOfProcHelper.InProc) {
394                         char[] charBuffer = GetCharArray_Unchecked( sink, getters, ordinal );
395                         result = new SqlChars( charBuffer );
396                     }
397                     else {    // InProc only
398                         Stream s = new SmiGettersStream( sink, getters, ordinal, metaData );
399                         SqlStreamChars sc = CopyIntoNewSmiScratchStreamChars( s, sink, context );
400                         result = new SqlChars( sc );
401                     }
402                 }
403             }
404             else {
405                 SqlString stringValue;
406                 if (SqlDbType.Xml == metaData.SqlDbType) {
407                     SqlXml xmlValue = GetSqlXml_Unchecked( sink, getters, ordinal, null );
408
409                     if (xmlValue.IsNull) {
410                         result = SqlChars.Null;
411                     }
412                     else {
413                         result = new SqlChars( xmlValue.Value.ToCharArray() );
414                     }
415                 }
416                 else {
417                     object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
418                     if (null == obj) {
419                         throw ADP.InvalidCast();
420                     }
421                     stringValue = (SqlString) obj;
422
423                     if ( stringValue.IsNull ) {
424                         result = SqlChars.Null;
425                     }
426                     else {
427                         result = new SqlChars( stringValue.Value.ToCharArray() );
428                     }
429                 }
430             }
431
432             return result;
433         }
434
435         internal static SqlDateTime GetSqlDateTime( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
436             SqlDateTime result;
437             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlDateTime ) ) {
438                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
439                     result = SqlDateTime.Null;
440                 }
441                 else {
442                     DateTime temp = GetDateTime_Unchecked( sink, getters, ordinal );
443                     result = new SqlDateTime( temp );
444                 }
445             }
446             else {
447                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
448                 if (null == obj) {
449                     throw ADP.InvalidCast();
450                 }
451                 result = (SqlDateTime) obj;
452             }
453
454             return result;
455         }
456
457         internal static SqlDecimal GetSqlDecimal( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
458             SqlDecimal result;
459             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlDecimal ) ) {
460                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
461                     result = SqlDecimal.Null;
462                 }
463                 else {
464                     result = GetSqlDecimal_Unchecked( sink, getters, ordinal );
465                 }
466             }
467             else {
468                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
469                 if (null == obj) {
470                     throw ADP.InvalidCast();
471                 }
472                 result = (SqlDecimal) obj;
473             }
474
475             return result;
476         }
477
478         internal static SqlDouble GetSqlDouble( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
479             SqlDouble result;
480             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlDouble ) ) {
481                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
482                     result = SqlDouble.Null;
483                 }
484                 else {
485                     Double temp = GetDouble_Unchecked( sink, getters, ordinal );
486                     result = new SqlDouble( temp );
487                 }
488             }
489             else {
490                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
491                 if (null == obj) {
492                     throw ADP.InvalidCast();
493                 }
494                 result = (SqlDouble) obj;
495             }
496
497             return result;
498         }
499
500         internal static SqlGuid GetSqlGuid( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
501             SqlGuid result;
502             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlGuid ) ) {
503                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
504                     result = SqlGuid.Null;
505                 }
506                 else {
507                     Guid temp = GetGuid_Unchecked( sink, getters, ordinal );
508                     result = new SqlGuid( temp );
509                 }
510             }
511             else {
512                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
513                 if (null == obj) {
514                     throw ADP.InvalidCast();
515                 }
516                 result = (SqlGuid) obj;
517             }
518
519             return result;
520         }
521
522         internal static SqlInt16 GetSqlInt16( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
523             SqlInt16 result;
524             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlInt16 ) ) {
525                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
526                     result = SqlInt16.Null;
527                 }
528                 else {
529                     Int16 temp = GetInt16_Unchecked( sink, getters, ordinal );
530                     result = new SqlInt16( temp );
531                 }
532             }
533             else {
534                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
535                 if (null == obj) {
536                     throw ADP.InvalidCast();
537                 }
538                 result = (SqlInt16) obj;
539             }
540
541             return result;
542         }
543
544         internal static SqlInt32 GetSqlInt32( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
545             SqlInt32 result;
546             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlInt32 ) ) {
547                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
548                     result = SqlInt32.Null;
549                 }
550                 else {
551                     Int32 temp = GetInt32_Unchecked( sink, getters, ordinal );
552                     result = new SqlInt32( temp );
553                 }
554             }
555             else {
556                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
557                 if (null == obj) {
558                     throw ADP.InvalidCast();
559                 }
560                 result = (SqlInt32) obj;
561             }
562             return result;
563         }
564
565         internal static SqlInt64 GetSqlInt64( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
566             SqlInt64 result;
567             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlInt64 ) ) {
568                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
569                     result = SqlInt64.Null;
570                 }
571                 else {
572                     Int64 temp = GetInt64_Unchecked( sink, getters, ordinal );
573                     result = new SqlInt64( temp );
574                 }
575             }
576             else {
577                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
578                 if (null == obj) {
579                     throw ADP.InvalidCast();
580                 }
581                 result = (SqlInt64) obj;
582             }
583
584             return result;
585         }
586
587         internal static SqlMoney GetSqlMoney( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
588             SqlMoney result;
589             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlMoney ) ) {
590                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
591                     result = SqlMoney.Null;
592                 }
593                 else {
594                     result = GetSqlMoney_Unchecked( sink, getters, ordinal );
595                 }
596             }
597             else {
598                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
599                 if (null == obj) {
600                     throw ADP.InvalidCast();
601                 }
602                 result = (SqlMoney) obj;
603             }
604
605             return result;
606         }
607
608         internal static SqlSingle GetSqlSingle( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
609             SqlSingle result;
610             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlSingle ) ) {
611                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
612                     result = SqlSingle.Null;
613                 }
614                 else {
615                     Single temp = GetSingle_Unchecked( sink, getters, ordinal );
616                     result = new SqlSingle( temp );
617                 }
618             }
619             else {
620                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
621                 if (null == obj) {
622                     throw ADP.InvalidCast();
623                 }
624                 result = (SqlSingle) obj;
625             }
626
627             return result;
628         }
629
630         internal static SqlString GetSqlString( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
631             SqlString result;
632             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlString ) ) {
633                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
634                     result = SqlString.Null;
635                 }
636                 else {
637                     String temp = GetString_Unchecked( sink, getters, ordinal );
638                     result = new SqlString( temp );
639                 }
640             }
641             else if (SqlDbType.Xml == metaData.SqlDbType) {
642                 SqlXml xmlValue = GetSqlXml_Unchecked( sink, getters, ordinal, null );
643                 
644                 if (xmlValue.IsNull) {
645                     result = SqlString.Null;
646                 }
647                 else {
648                     result = new SqlString( xmlValue.Value );
649                 }
650             }
651             else {
652                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
653                 if (null == obj) {
654                     throw ADP.InvalidCast();
655                 }
656                 result = (SqlString) obj;
657             }
658
659             return result;
660         }
661
662         internal static SqlXml GetSqlXml( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context ) {
663             SqlXml result;
664             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.SqlXml ) ) {
665                 if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
666                     result = SqlXml.Null;
667                 }
668                 else {
669                     result = GetSqlXml_Unchecked( sink, getters, ordinal, context );
670                 }
671             }
672             else {
673                 object obj = GetSqlValue( sink, getters, ordinal, metaData, null  );
674                 if (null == obj) {
675                     throw ADP.InvalidCast();
676                 }
677                 result = (SqlXml) obj;
678             }
679
680             return result;
681         }
682
683         internal static String GetString( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
684             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
685             if ( CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.String ) ) {
686                 return GetString_Unchecked( sink, getters, ordinal );
687             }
688             object obj = GetValue( sink, getters, ordinal, metaData, null  );
689             if (null == obj) {
690                 throw ADP.InvalidCast();
691             }
692             return (String) obj;
693         }
694
695         internal static SqlSequentialStreamSmi GetSequentialStream( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false ) {
696             Debug.Assert( !ValueUtilsSmi.IsDBNull_Unchecked( sink, getters, ordinal ), "Should not try to get a SqlSequentialStreamSmi on a null column" );
697             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
698             if ( ( !bypassTypeCheck ) && ( !CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.Stream ) ) ) {
699                 throw ADP.InvalidCast();
700             }
701
702             // This will advance the column to ordinal
703             long length = GetBytesLength_Unchecked(sink, getters, ordinal);
704             return new SqlSequentialStreamSmi(sink, getters, ordinal, length);
705         }
706
707         internal static SqlSequentialTextReaderSmi GetSequentialTextReader( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
708             Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialTextReaderSmi on a null column");
709             ThrowIfITypedGettersIsNull( sink, getters, ordinal );
710             if ( !CanAccessGetterDirectly( metaData, ExtendedClrTypeCode.TextReader ) ) {
711                 throw ADP.InvalidCast();
712             }
713
714             // This will advance the column to ordinal
715             long length = GetCharsLength_Unchecked(sink, getters, ordinal);
716             return new SqlSequentialTextReaderSmi(sink, getters, ordinal, length);
717         }
718
719         internal static Stream GetStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) {
720             bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal);
721
722             // If a sql_variant, get the internal type
723             if ( !bypassTypeCheck ) {
724                 if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) {
725                     metaData = getters.GetVariantType(sink, ordinal);
726                 }
727                 // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast
728                 if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) {
729                     throw ADP.InvalidCast();
730                 }
731             }
732
733             byte[] data;
734             if (isDbNull) {
735                 // "null" stream
736                 data = new byte[0];
737             }
738             else {
739                 // Read all data
740                 data = GetByteArray_Unchecked(sink, getters, ordinal);
741             }
742
743             // Wrap data in pre-built object
744             return new MemoryStream(data, writable: false);
745         }
746
747         internal static TextReader GetTextReader( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
748             bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal);
749
750             // If a sql_variant, get the internal type
751             if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) {
752                 metaData = getters.GetVariantType(sink, ordinal);
753             }
754             // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast
755             if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader))) {
756                 throw ADP.InvalidCast();
757             }
758
759             string data;
760             if (isDbNull) {
761                 // "null" textreader
762                 data = string.Empty;
763             }
764             else {
765                 // Read all data
766                 data = GetString_Unchecked(sink, getters, ordinal);
767             }
768
769             // Wrap in pre-built object
770             return new StringReader(data);
771         }
772         
773         // calling GetTimeSpan on possibly v100 SMI
774         internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) {
775             if (gettersSupportKatmaiDateTime) {
776                 return GetTimeSpan(sink, (SmiTypedGetterSetter)getters, ordinal, metaData);
777             }
778             ThrowIfITypedGettersIsNull(sink, getters, ordinal);
779             object obj = GetValue(sink, getters, ordinal, metaData, null);
780             if (null == obj) {
781                 throw ADP.InvalidCast();
782             }
783             return (TimeSpan) obj;
784         }
785
786         // dealing with v200 SMI
787         internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) {
788             ThrowIfITypedGettersIsNull(sink, getters, ordinal);
789             if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TimeSpan)) {
790                 return GetTimeSpan_Unchecked(sink, getters, ordinal);
791             }
792             return (TimeSpan)GetValue200(sink, getters, ordinal, metaData, null);
793         }
794         
795         // GetValue() for v200 SMI (new Katmai Date/Time types)
796         internal static object GetValue200(
797             SmiEventSink_Default sink,
798             SmiTypedGetterSetter getters,
799             int ordinal,
800             SmiMetaData metaData,
801             SmiContext context
802             ) {
803             object result = null;
804             if (IsDBNull_Unchecked(sink, getters, ordinal)) {
805                 result = DBNull.Value;
806             } else {
807                 switch (metaData.SqlDbType) {
808                     case SqlDbType.Variant:  // Handle variants specifically for v200, since they could contain v200 types
809                         metaData = getters.GetVariantType(sink, ordinal);
810                         sink.ProcessMessagesAndThrow();
811                         Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!");
812                         result = GetValue200(sink, getters, ordinal, metaData, context);
813                         break;
814                     case SqlDbType.Date:
815                     case SqlDbType.DateTime2:
816                         result = GetDateTime_Unchecked(sink, getters, ordinal);
817                         break;
818                     case SqlDbType.Time:
819                         result = GetTimeSpan_Unchecked(sink, getters, ordinal);
820                         break;
821                     case SqlDbType.DateTimeOffset:
822                         result = GetDateTimeOffset_Unchecked(sink, getters, ordinal);
823                         break;
824                     default:
825                         result = GetValue(sink, getters, ordinal, metaData, context);
826                         break;
827                 }
828             }
829
830             return result;
831         }
832
833         //  implements SqlClient 1.1-compatible GetValue() semantics for everything except output parameters
834         internal static object GetValue(
835             SmiEventSink_Default    sink,
836             ITypedGettersV3         getters,
837             int                     ordinal,
838             SmiMetaData             metaData,
839             SmiContext              context
840             ) {
841             object result = null;
842             if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
843                 result = DBNull.Value;
844             }
845             else {
846                 switch( metaData.SqlDbType ) {
847                     case SqlDbType.BigInt:
848                         result = GetInt64_Unchecked( sink, getters, ordinal );
849                         break;
850                     case SqlDbType.Binary:
851                         result = GetByteArray_Unchecked( sink, getters, ordinal );
852                         break;
853                     case SqlDbType.Bit:
854                         result = GetBoolean_Unchecked( sink, getters, ordinal );
855                         break;
856                     case SqlDbType.Char:
857                         result = GetString_Unchecked( sink, getters, ordinal );
858                         break;
859                     case SqlDbType.DateTime:
860                         result = GetDateTime_Unchecked( sink, getters, ordinal );
861                         break;
862                     case SqlDbType.Decimal:
863                         result = GetSqlDecimal_Unchecked( sink, getters, ordinal ).Value;
864                         break;
865                     case SqlDbType.Float:
866                         result = GetDouble_Unchecked( sink, getters, ordinal );
867                         break;
868                     case SqlDbType.Image:
869                         result = GetByteArray_Unchecked( sink, getters, ordinal );
870                         break;
871                     case SqlDbType.Int:
872                         result = GetInt32_Unchecked( sink, getters, ordinal );
873                         break;
874                     case SqlDbType.Money:
875                         result = GetSqlMoney_Unchecked( sink, getters, ordinal ).Value;
876                         break;
877                     case SqlDbType.NChar: 
878                         result = GetString_Unchecked( sink, getters, ordinal );
879                         break;
880                     case SqlDbType.NText: 
881                         result = GetString_Unchecked( sink, getters, ordinal );
882                         break;
883                     case SqlDbType.NVarChar: 
884                         result = GetString_Unchecked( sink, getters, ordinal );
885                         break;
886                     case SqlDbType.Real:
887                         result = GetSingle_Unchecked( sink, getters, ordinal );
888                         break;
889                     case SqlDbType.UniqueIdentifier:
890                         result = GetGuid_Unchecked( sink, getters, ordinal );
891                         break;
892                     case SqlDbType.SmallDateTime:
893                         result = GetDateTime_Unchecked( sink, getters, ordinal );
894                         break;
895                     case SqlDbType.SmallInt:
896                         result = GetInt16_Unchecked( sink, getters, ordinal );
897                         break;
898                     case SqlDbType.SmallMoney:
899                         result = GetSqlMoney_Unchecked( sink, getters, ordinal ).Value;
900                         break;
901                     case SqlDbType.Text:
902                         result = GetString_Unchecked( sink, getters, ordinal );
903                         break;
904                     case SqlDbType.Timestamp:
905                         result = GetByteArray_Unchecked( sink, getters, ordinal );
906                         break;
907                     case SqlDbType.TinyInt:
908                         result = GetByte_Unchecked( sink, getters, ordinal );
909                         break;
910                     case SqlDbType.VarBinary:
911                         result = GetByteArray_Unchecked( sink, getters, ordinal );
912                         break;
913                     case SqlDbType.VarChar:
914                         result = GetString_Unchecked( sink, getters, ordinal );
915                         break;
916                     case SqlDbType.Variant:
917                         metaData = getters.GetVariantType( sink, ordinal );
918                         sink.ProcessMessagesAndThrow();
919                         Debug.Assert( SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!" );
920                         result = GetValue( sink, getters, ordinal, metaData, context );
921                         break;
922                     case SqlDbType.Xml:
923                         result = GetSqlXml_Unchecked( sink, getters, ordinal, context ).Value;
924                         break;
925                     case SqlDbType.Udt:
926                         result = GetUdt_LengthChecked( sink, getters, ordinal, metaData );
927                         break;
928                 }
929             }
930
931             return result;
932         }
933
934         // dealing with v200 SMI
935         internal static object GetSqlValue200(
936             SmiEventSink_Default sink,
937             SmiTypedGetterSetter getters,
938             int ordinal,
939             SmiMetaData metaData,
940             SmiContext context
941             ) {
942             object result = null;
943             if (IsDBNull_Unchecked(sink, getters, ordinal)) {
944                 if (SqlDbType.Udt == metaData.SqlDbType) {
945                     result = NullUdtInstance(metaData);
946                 } else {
947                     result = __typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
948                 }
949             } else {
950                 switch (metaData.SqlDbType) {
951                     case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types
952                         metaData = getters.GetVariantType(sink, ordinal);
953                         sink.ProcessMessagesAndThrow();
954                         Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!");
955                         result = GetSqlValue200(sink, getters, ordinal, metaData, context);
956                         break;
957                     case SqlDbType.Date:
958                     case SqlDbType.DateTime2:
959                         result = GetDateTime_Unchecked(sink, getters, ordinal);
960                         break;
961                     case SqlDbType.Time:
962                         result = GetTimeSpan_Unchecked(sink, getters, ordinal);
963                         break;
964                     case SqlDbType.DateTimeOffset:
965                         result = GetDateTimeOffset_Unchecked(sink, getters, ordinal);
966                         break;
967                     default:
968                         result = GetSqlValue(sink, getters, ordinal, metaData, context);
969                         break;
970                 }
971             }
972
973             return result;
974         }
975
976         //  implements SqlClient 1.1-compatible GetSqlValue() semantics for everything except output parameters
977         internal static object GetSqlValue(
978             SmiEventSink_Default    sink,
979             ITypedGettersV3         getters,
980             int                     ordinal,
981             SmiMetaData             metaData,
982             SmiContext              context
983             ) {
984             object result = null;
985             if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
986                 if (SqlDbType.Udt == metaData.SqlDbType) {
987                     result = NullUdtInstance(metaData);
988                 }
989                 else {
990                     result = __typeSpecificNullForSqlValue[(int)metaData.SqlDbType];
991                 }
992             }
993             else {
994                 switch( metaData.SqlDbType ) {
995                     case SqlDbType.BigInt:
996                         result = new SqlInt64( GetInt64_Unchecked( sink, getters, ordinal ) );
997                         break;
998                     case SqlDbType.Binary:
999                         result = GetSqlBinary_Unchecked( sink, getters, ordinal );
1000                         break;
1001                     case SqlDbType.Bit:
1002                         result = new SqlBoolean( GetBoolean_Unchecked( sink, getters, ordinal ) );
1003                         break;
1004                     case SqlDbType.Char:
1005                         result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
1006                         break;
1007                     case SqlDbType.DateTime:
1008                         result = new SqlDateTime( GetDateTime_Unchecked( sink, getters, ordinal ) );
1009                         break;
1010                     case SqlDbType.Decimal:
1011                         result = GetSqlDecimal_Unchecked( sink, getters, ordinal );
1012                         break;
1013                     case SqlDbType.Float:
1014                         result = new SqlDouble( GetDouble_Unchecked( sink, getters, ordinal ) );
1015                         break;
1016                     case SqlDbType.Image:
1017                         result = GetSqlBinary_Unchecked( sink, getters, ordinal );
1018                         break;
1019                     case SqlDbType.Int:
1020                         result = new SqlInt32( GetInt32_Unchecked( sink, getters, ordinal ) );
1021                         break;
1022                     case SqlDbType.Money:
1023                         result = GetSqlMoney_Unchecked( sink, getters, ordinal );
1024                         break;
1025                     case SqlDbType.NChar: 
1026                         result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
1027                         break;
1028                     case SqlDbType.NText: 
1029                         result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
1030                         break;
1031                     case SqlDbType.NVarChar: 
1032                         result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
1033                         break;
1034                     case SqlDbType.Real:
1035                         result = new SqlSingle( GetSingle_Unchecked( sink, getters, ordinal ) );
1036                         break;
1037                     case SqlDbType.UniqueIdentifier:
1038                         result = new SqlGuid( GetGuid_Unchecked( sink, getters, ordinal ) );
1039                         break;
1040                     case SqlDbType.SmallDateTime:
1041                         result = new SqlDateTime( GetDateTime_Unchecked( sink, getters, ordinal ) );
1042                         break;
1043                     case SqlDbType.SmallInt:
1044                         result = new SqlInt16( GetInt16_Unchecked( sink, getters, ordinal ) );
1045                         break;
1046                     case SqlDbType.SmallMoney:
1047                         result = GetSqlMoney_Unchecked( sink, getters, ordinal );
1048                         break;
1049                     case SqlDbType.Text:
1050                         result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
1051                         break;
1052                     case SqlDbType.Timestamp:
1053                         result = GetSqlBinary_Unchecked( sink, getters, ordinal );
1054                         break;
1055                     case SqlDbType.TinyInt:
1056                         result = new SqlByte( GetByte_Unchecked( sink, getters, ordinal ) );
1057                         break;
1058                     case SqlDbType.VarBinary:
1059                         result = GetSqlBinary_Unchecked( sink, getters, ordinal );
1060                         break;
1061                     case SqlDbType.VarChar:
1062                         result = new SqlString( GetString_Unchecked( sink, getters, ordinal ) );
1063                         break;
1064                     case SqlDbType.Variant:
1065                         metaData = getters.GetVariantType( sink, ordinal );
1066                         sink.ProcessMessagesAndThrow();
1067                         Debug.Assert( SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!" );
1068                         result = GetSqlValue( sink, getters, ordinal, metaData, context );
1069                         break;
1070                     case SqlDbType.Xml: 
1071                         result = GetSqlXml_Unchecked( sink, getters, ordinal, context );
1072                         break;
1073                     case SqlDbType.Udt:
1074                         result = GetUdt_LengthChecked( sink, getters, ordinal, metaData );
1075                         break;
1076                 }
1077             }
1078
1079             return result;
1080         }
1081
1082         // null return values for SqlClient 1.1-compatible GetSqlValue()
1083         private static object[] __typeSpecificNullForSqlValue = {
1084             SqlInt64.Null,      // SqlDbType.BigInt
1085             SqlBinary.Null,     // SqlDbType.Binary
1086             SqlBoolean.Null,    // SqlDbType.Bit
1087             SqlString.Null,     // SqlDbType.Char
1088             SqlDateTime.Null,   // SqlDbType.DateTime
1089             SqlDecimal.Null,    // SqlDbType.Decimal
1090             SqlDouble.Null,     // SqlDbType.Float
1091             SqlBinary.Null,     // SqlDbType.Image
1092             SqlInt32.Null,      // SqlDbType.Int
1093             SqlMoney.Null,      // SqlDbType.Money
1094             SqlString.Null,     // SqlDbType.NChar
1095             SqlString.Null,     // SqlDbType.NText
1096             SqlString.Null,     // SqlDbType.NVarChar
1097             SqlSingle.Null,     // SqlDbType.Real
1098             SqlGuid.Null,       // SqlDbType.UniqueIdentifier
1099             SqlDateTime.Null,   // SqlDbType.SmallDateTime
1100             SqlInt16.Null,      // SqlDbType.SmallInt
1101             SqlMoney.Null,      // SqlDbType.SmallMoney
1102             SqlString.Null,     // SqlDbType.Text
1103             SqlBinary.Null,     // SqlDbType.Timestamp
1104             SqlByte.Null,       // SqlDbType.TinyInt
1105             SqlBinary.Null,     // SqlDbType.VarBinary
1106             SqlString.Null,     // SqlDbType.VarChar
1107             DBNull.Value,       // SqlDbType.Variant
1108             null,               // 24
1109             SqlXml.Null,        // SqlDbType.Xml
1110             null,               // 26
1111             null,               // 27
1112             null,               // 28
1113             null,               // SqlDbType.Udt -- requires instantiating udt-specific type
1114             null,               // SqlDbType.Structured
1115             DBNull.Value,       // SqlDbType.Date
1116             DBNull.Value,       // SqlDbType.Time
1117             DBNull.Value,       // SqlDbType.DateTime2
1118             DBNull.Value,       // SqlDbType.DateTimeOffset
1119         };
1120
1121         internal static object NullUdtInstance(SmiMetaData metaData) {
1122             Type t = metaData.Type;
1123             Debug.Assert(t != null, "Unexpected null of Udt type on NullUdtInstance!");
1124             return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[]{}, CultureInfo.InvariantCulture);
1125         }
1126
1127         internal static SqlBuffer.StorageType SqlDbTypeToStorageType(SqlDbType dbType) {
1128             int index = unchecked((int)dbType);
1129             Debug.Assert(index >= 0 && index < __dbTypeToStorageType.Length, string.Format(CultureInfo.InvariantCulture, "Unexpected dbType value: {0}", dbType));
1130             return __dbTypeToStorageType[index];
1131         }
1132
1133         private static void GetNullOutputParameterSmi(SmiMetaData metaData, SqlBuffer targetBuffer, ref object result) {
1134             if (SqlDbType.Udt == metaData.SqlDbType) {
1135                 result = NullUdtInstance(metaData);
1136             }
1137             else {
1138                 SqlBuffer.StorageType stype = SqlDbTypeToStorageType(metaData.SqlDbType);
1139                 if ( SqlBuffer.StorageType.Empty == stype ) {
1140                     result = DBNull.Value;
1141                 }
1142                 else if (SqlBuffer.StorageType.SqlBinary == stype) {
1143                     // special case SqlBinary, 'cause tds parser never sets SqlBuffer to null, just to empty!
1144                     targetBuffer.SqlBinary = SqlBinary.Null;
1145                 }
1146                 else if (SqlBuffer.StorageType.SqlGuid == stype) {
1147                     targetBuffer.SqlGuid = SqlGuid.Null;
1148                 }
1149                 else {
1150                     targetBuffer.SetToNullOfType( stype );
1151                 }
1152             }
1153         }
1154
1155         // UDTs and null variants come back via return value, all else is via targetBuffer.
1156         //  implements SqlClient 2.0-compatible output parameter semantics
1157         internal static object GetOutputParameterV3Smi(
1158             SmiEventSink_Default    sink,                   // event sink for errors
1159             ITypedGettersV3         getters,                // getters interface to grab value from
1160             int                     ordinal,                // parameter within getters
1161             SmiMetaData             metaData,               // Getter's type for this ordinal
1162             SmiContext              context,                // used to obtain scratch streams
1163             SqlBuffer               targetBuffer            // destination
1164             ) {
1165             object result = null;   // Workaround for UDT hack in non-Smi code paths.
1166             if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
1167                 GetNullOutputParameterSmi(metaData, targetBuffer, ref result);
1168             }
1169             else {
1170                 switch( metaData.SqlDbType )
1171                     {
1172                     case SqlDbType.BigInt:
1173                         targetBuffer.Int64 = GetInt64_Unchecked( sink, getters, ordinal );
1174                         break;
1175                     case SqlDbType.Binary:
1176                     case SqlDbType.Image:
1177                     case SqlDbType.Timestamp:
1178                     case SqlDbType.VarBinary:
1179                         targetBuffer.SqlBinary = GetSqlBinary_Unchecked( sink, getters, ordinal );
1180                         break;
1181                     case SqlDbType.Bit:
1182                         targetBuffer.Boolean = GetBoolean_Unchecked( sink, getters, ordinal );
1183                         break;
1184                     case SqlDbType.NChar:
1185                     case SqlDbType.NText:
1186                     case SqlDbType.NVarChar:
1187                     case SqlDbType.Char:
1188                     case SqlDbType.VarChar:
1189                     case SqlDbType.Text:
1190                         targetBuffer.SetToString( GetString_Unchecked( sink, getters, ordinal ) );
1191                         break;
1192                     case SqlDbType.DateTime:
1193                     case SqlDbType.SmallDateTime: {
1194                         SqlDateTime dt = new SqlDateTime( GetDateTime_Unchecked( sink, getters, ordinal ) );
1195                         targetBuffer.SetToDateTime( dt.DayTicks, dt.TimeTicks );
1196                         break;
1197                     }
1198                     case SqlDbType.Decimal: {
1199                         SqlDecimal dec = GetSqlDecimal_Unchecked( sink, getters, ordinal );
1200                         targetBuffer.SetToDecimal( dec.Precision, dec.Scale, dec.IsPositive, dec.Data );
1201                         break;
1202                     }
1203                     case SqlDbType.Float:
1204                         targetBuffer.Double = GetDouble_Unchecked( sink, getters, ordinal );
1205                         break;
1206                     case SqlDbType.Int:
1207                         targetBuffer.Int32 = GetInt32_Unchecked( sink, getters, ordinal );
1208                         break;
1209                     case SqlDbType.Money:
1210                     case SqlDbType.SmallMoney:
1211                         targetBuffer.SetToMoney( GetInt64_Unchecked( sink, getters, ordinal) );
1212                         break;
1213                     case SqlDbType.Real:
1214                         targetBuffer.Single = GetSingle_Unchecked( sink, getters, ordinal );
1215                         break;
1216                     case SqlDbType.UniqueIdentifier:
1217                         targetBuffer.SqlGuid = new SqlGuid( GetGuid_Unchecked( sink, getters, ordinal ) );
1218                         break;
1219                     case SqlDbType.SmallInt:
1220                         targetBuffer.Int16 = GetInt16_Unchecked( sink, getters, ordinal );
1221                         break;
1222                     case SqlDbType.TinyInt:
1223                         targetBuffer.Byte = GetByte_Unchecked( sink, getters, ordinal );
1224                         break;
1225                     case SqlDbType.Variant:
1226                         // For variants, recur using the current value's sqldbtype
1227                         metaData = getters.GetVariantType( sink, ordinal );
1228                         sink.ProcessMessagesAndThrow();
1229                         Debug.Assert( SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!" );
1230                         GetOutputParameterV3Smi( sink, getters, ordinal, metaData, context, targetBuffer );
1231                         break;
1232                     case SqlDbType.Udt:
1233                         result = GetUdt_LengthChecked( sink, getters, ordinal, metaData );
1234                                         break;
1235                                 case SqlDbType.Xml:
1236                         targetBuffer.SqlXml = GetSqlXml_Unchecked( sink, getters, ordinal, null );
1237                         break;
1238                     default:
1239                         Debug.Assert( false, "Unexpected SqlDbType" );
1240                         break;
1241                     }
1242             }
1243
1244             return result;
1245         }
1246
1247         // UDTs and null variants come back via return value, all else is via targetBuffer.
1248         //  implements SqlClient 1.1-compatible output parameter semantics
1249         internal static object GetOutputParameterV200Smi(
1250             SmiEventSink_Default    sink,                   // event sink for errors
1251             SmiTypedGetterSetter    getters,                // getters interface to grab value from
1252             int                     ordinal,                // parameter within getters
1253             SmiMetaData             metaData,               // Getter's type for this ordinal
1254             SmiContext              context,                // used to obtain scratch streams
1255             SqlBuffer               targetBuffer            // destination
1256             ) {
1257             object result = null;   // Workaround for UDT hack in non-Smi code paths.
1258             if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
1259                 GetNullOutputParameterSmi(metaData, targetBuffer, ref result);
1260             }
1261             else {
1262                 switch(metaData.SqlDbType) {
1263                     // new types go here
1264                     case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types
1265                         // For variants, recur using the current value's sqldbtype
1266                         metaData = getters.GetVariantType( sink, ordinal );
1267                         sink.ProcessMessagesAndThrow();
1268                         Debug.Assert( SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!" );
1269                         GetOutputParameterV200Smi( sink, getters, ordinal, metaData, context, targetBuffer );
1270                         break;
1271                     case SqlDbType.Date:
1272                         targetBuffer.SetToDate(GetDateTime_Unchecked(sink, getters, ordinal));
1273                         break;
1274                     case SqlDbType.DateTime2:
1275                         targetBuffer.SetToDateTime2(GetDateTime_Unchecked(sink, getters, ordinal), metaData.Scale);
1276                         break;
1277                     case SqlDbType.Time:
1278                         targetBuffer.SetToTime(GetTimeSpan_Unchecked(sink, getters, ordinal), metaData.Scale);
1279                         break;
1280                     case SqlDbType.DateTimeOffset:
1281                         targetBuffer.SetToDateTimeOffset(GetDateTimeOffset_Unchecked(sink, getters, ordinal), metaData.Scale);
1282                         break;
1283                     default:
1284                         result = GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer);
1285                         break;
1286                 }
1287             }
1288
1289             return result;
1290         }
1291
1292         private static SqlBuffer.StorageType[] __dbTypeToStorageType = new SqlBuffer.StorageType[] {
1293             SqlBuffer.StorageType.Int64,            // BigInt
1294             SqlBuffer.StorageType.SqlBinary,        // Binary
1295             SqlBuffer.StorageType.Boolean,          // Bit
1296             SqlBuffer.StorageType.String,           // Char
1297             SqlBuffer.StorageType.DateTime,         // DateTime
1298             SqlBuffer.StorageType.Decimal,          // Decimal
1299             SqlBuffer.StorageType.Double,           // Float
1300             SqlBuffer.StorageType.SqlBinary,        // Image
1301             SqlBuffer.StorageType.Int32,            // Int
1302             SqlBuffer.StorageType.Money,            // Money
1303             SqlBuffer.StorageType.String,           // NChar 
1304             SqlBuffer.StorageType.String,           // NText 
1305             SqlBuffer.StorageType.String,           // NVarChar 
1306             SqlBuffer.StorageType.Single,           // Real
1307             SqlBuffer.StorageType.SqlGuid,          // UniqueIdentifier
1308             SqlBuffer.StorageType.DateTime,         // SmallDateTime
1309             SqlBuffer.StorageType.Int16,            // SmallInt
1310             SqlBuffer.StorageType.Money,            // SmallMoney
1311             SqlBuffer.StorageType.String,           // Text
1312             SqlBuffer.StorageType.SqlBinary,        // Timestamp
1313             SqlBuffer.StorageType.Byte,             // TinyInt
1314             SqlBuffer.StorageType.SqlBinary,        // VarBinary
1315             SqlBuffer.StorageType.String,           // VarChar
1316             SqlBuffer.StorageType.Empty,            // Variant
1317             SqlBuffer.StorageType.Empty,            // 24
1318             SqlBuffer.StorageType.SqlXml,           // Xml
1319             SqlBuffer.StorageType.Empty,            // 26
1320             SqlBuffer.StorageType.Empty,            // 27
1321             SqlBuffer.StorageType.Empty,            // 28
1322             SqlBuffer.StorageType.Empty,            // Udt
1323             SqlBuffer.StorageType.Empty,            // Structured
1324             SqlBuffer.StorageType.Date,             // Date
1325             SqlBuffer.StorageType.Time,             // Time
1326             SqlBuffer.StorageType.DateTime2,        // DateTime2
1327             SqlBuffer.StorageType.DateTimeOffset,   // DateTimeOffset
1328         };
1329
1330         // Strongly-typed setters are a bit simpler than their corresponding getters.
1331         //      1) check to make sure the type is compatible (exception if not)
1332         //      2) push the data
1333         internal static void SetDBNull( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Boolean value ) {
1334             SetDBNull_Unchecked( sink, setters, ordinal );
1335         }
1336
1337         internal static void SetBoolean( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Boolean value ) {
1338             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Boolean );
1339
1340             SetBoolean_Unchecked( sink, setters, ordinal, value ); 
1341         }
1342
1343         internal static void SetByte( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Byte value ) {
1344             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Byte );
1345
1346             SetByte_Unchecked( sink, setters, ordinal, value ); 
1347         }
1348
1349         internal static long SetBytes( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length ) {
1350             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.ByteArray );
1351             if ( null == buffer ) {
1352                 throw ADP.ArgumentNull( "buffer" );
1353             }
1354             length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length );
1355             Debug.Assert( length >= 0, "Buffer.Length was invalid!" );
1356             if (0==length) {
1357                 // Front end semantics says to ignore fieldOffset and bufferOffset
1358                 //  if not doing any actual work.
1359                 // Back end semantics says they must be valid, even for no work.
1360                 // Compensate by setting offsets to zero here (valid for any scenario)
1361                 fieldOffset = 0;
1362                 bufferOffset = 0;
1363             }
1364             return SetBytes_Unchecked( sink, setters, ordinal, fieldOffset, buffer, bufferOffset, length );
1365         }
1366
1367         internal static long SetBytesLength( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long length ) {
1368             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.ByteArray );
1369
1370             if ( length < 0 ) {
1371                 throw ADP.InvalidDataLength( length );
1372             }
1373
1374             if ( metaData.MaxLength >= 0 && length > metaData.MaxLength ) {
1375                 length = metaData.MaxLength;
1376             }
1377
1378             setters.SetBytesLength( sink, ordinal, length );
1379             sink.ProcessMessagesAndThrow();
1380
1381             return length;
1382         }
1383
1384         internal static long SetChars( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long fieldOffset, char[] buffer, int bufferOffset, int length ) {
1385             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.CharArray );
1386             if ( null == buffer ) {
1387                 throw ADP.ArgumentNull( "buffer" );
1388             }
1389             length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length );
1390             Debug.Assert( length >= 0, "Buffer.Length was invalid!" );
1391             if (0==length) {
1392                 // Front end semantics says to ignore fieldOffset and bufferOffset
1393                 //  if not doing any actual work.
1394                 // Back end semantics says they must be valid, even for no work.
1395                 // Compensate by setting offsets to zero here (valid for any scenario)
1396                 fieldOffset = 0;
1397                 bufferOffset = 0;
1398             }
1399             return SetChars_Unchecked( sink, setters, ordinal, fieldOffset, buffer, bufferOffset, length );
1400         }
1401
1402         internal static void SetDateTime( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value ) {
1403             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.DateTime );
1404
1405             SetDateTime_Checked( sink, setters, ordinal, metaData, value ); 
1406         }
1407
1408         internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value, bool settersSupportKatmaiDateTime) {
1409             if (!settersSupportKatmaiDateTime) {
1410                 throw ADP.InvalidCast();
1411             }
1412             ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTimeOffset);
1413             SetDateTimeOffset_Unchecked(sink, (SmiTypedGetterSetter)setters, ordinal, value);
1414         }
1415
1416         internal static void SetDecimal( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Decimal value ) {
1417             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Decimal );
1418
1419             SetDecimal_PossiblyMoney( sink, setters, ordinal, metaData, value ); 
1420         }
1421
1422         internal static void SetDouble( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Double value ) {
1423             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Double );
1424
1425             SetDouble_Unchecked( sink, setters, ordinal, value ); 
1426         }
1427
1428         internal static void SetGuid( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Guid value ) {
1429             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Guid );
1430
1431             SetGuid_Unchecked( sink, setters, ordinal, value ); 
1432         }
1433
1434         internal static void SetInt16( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int16 value ) {
1435             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Int16 );
1436
1437             SetInt16_Unchecked( sink, setters, ordinal, value ); 
1438         }
1439
1440         internal static void SetInt32( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int32 value ) {
1441             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Int32 );
1442
1443             SetInt32_Unchecked( sink, setters, ordinal, value ); 
1444         }
1445
1446         internal static void SetInt64( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int64 value ) {
1447             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Int64 );
1448
1449             SetInt64_Unchecked( sink, setters, ordinal, value ); 
1450         }
1451
1452         internal static void SetSingle( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Single value ) {
1453             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Single );
1454
1455             SetSingle_Unchecked( sink, setters, ordinal, value ); 
1456         }
1457
1458         internal static void SetSqlBinary( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBinary value ) {
1459             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlBinary );
1460             SetSqlBinary_LengthChecked( sink, setters, ordinal, metaData, value, 0 );
1461         }
1462
1463         internal static void SetSqlBoolean( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBoolean value ) {
1464             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlBoolean );
1465
1466             SetSqlBoolean_Unchecked( sink, setters, ordinal, value ); 
1467         }
1468
1469         internal static void SetSqlByte( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlByte value ) {
1470             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlByte );
1471
1472             SetSqlByte_Unchecked( sink, setters, ordinal, value ); 
1473         }
1474
1475         internal static void SetSqlBytes( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBytes value ) {
1476             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlBytes );
1477
1478             SetSqlBytes_LengthChecked( sink, setters, ordinal, metaData, value, 0 );
1479         }
1480
1481         internal static void SetSqlChars( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlChars value ) {
1482             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlChars );
1483             SetSqlChars_LengthChecked( sink, setters, ordinal, metaData, value, 0 );
1484         }
1485
1486         internal static void SetSqlDateTime( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDateTime value ) {
1487             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlDateTime );
1488
1489             SetSqlDateTime_Checked( sink, setters, ordinal, metaData, value ); 
1490         }
1491
1492         internal static void SetSqlDecimal( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDecimal value ) {
1493             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlDecimal );
1494
1495             SetSqlDecimal_Unchecked( sink, setters, ordinal, value ); 
1496         }
1497
1498         internal static void SetSqlDouble( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDouble value ) {
1499             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlDouble );
1500
1501             SetSqlDouble_Unchecked( sink, setters, ordinal, value ); 
1502         }
1503
1504         internal static void SetSqlGuid( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlGuid value ) {
1505             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlGuid );
1506
1507             SetSqlGuid_Unchecked( sink, setters, ordinal, value ); 
1508         }
1509
1510         internal static void SetSqlInt16( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt16 value ) {
1511             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlInt16 );
1512
1513             SetSqlInt16_Unchecked( sink, setters, ordinal, value ); 
1514         }
1515
1516         internal static void SetSqlInt32( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt32 value ) {
1517             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlInt32 );
1518
1519             SetSqlInt32_Unchecked( sink, setters, ordinal, value ); 
1520         }
1521
1522         internal static void SetSqlInt64( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt64 value ) {
1523             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlInt64 );
1524
1525             SetSqlInt64_Unchecked( sink, setters, ordinal, value ); 
1526         }
1527
1528         internal static void SetSqlMoney( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value ) {
1529             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlMoney );
1530
1531             SetSqlMoney_Checked( sink, setters, ordinal, metaData, value ); 
1532         }
1533
1534         internal static void SetSqlSingle( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlSingle value ) {
1535             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlSingle );
1536
1537             SetSqlSingle_Unchecked( sink, setters, ordinal, value ); 
1538         }
1539
1540         internal static void SetSqlString( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value ) {
1541             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlString );
1542             SetSqlString_LengthChecked( sink, setters, ordinal, metaData, value, 0 );
1543         }
1544
1545         internal static void SetSqlXml( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlXml value ) {
1546             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.SqlXml );
1547
1548             SetSqlXml_Unchecked( sink, setters, ordinal, value ); 
1549         }
1550
1551         internal static void SetString( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, String value ) {
1552             ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.String );
1553
1554             SetString_LengthChecked( sink, setters, ordinal, metaData, value, 0 );
1555         }
1556
1557         internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value, bool settersSupportKatmaiDateTime) {
1558             if (!settersSupportKatmaiDateTime) {
1559                 throw ADP.InvalidCast();
1560             }
1561             ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.TimeSpan);
1562             SetTimeSpan_Checked(sink, (SmiTypedGetterSetter)setters, ordinal, metaData, value);
1563         }
1564
1565         //  Implements SqlClient 2.0-compatible SetValue() semantics
1566         //      Assumes caller already validated type against the metadata, other than trimming lengths
1567         internal static void SetCompatibleValue(
1568             SmiEventSink_Default    sink,
1569             ITypedSettersV3         setters,
1570             int                     ordinal,
1571             SmiMetaData             metaData,       // metadata for target setter column
1572             object                  value, 
1573             ExtendedClrTypeCode     typeCode,
1574             int                     offset
1575             ) {
1576             // Ensure either an invalid type, or caller validated compatibility
1577             // SqlDbType.Variant and have special handling
1578             Debug.Assert(   typeCode == ExtendedClrTypeCode.Invalid || 
1579                             typeCode == ExtendedClrTypeCode.SByte ||
1580                             typeCode == ExtendedClrTypeCode.UInt16 ||
1581                             typeCode == ExtendedClrTypeCode.UInt32 ||
1582                             typeCode == ExtendedClrTypeCode.UInt64 ||
1583                             typeCode == ExtendedClrTypeCode.DBNull ||
1584                             typeCode == ExtendedClrTypeCode.Empty ||
1585                             CanAccessSetterDirectly( metaData, typeCode ) ||
1586                             value is DataFeed /* already validated */);
1587
1588             switch ( typeCode ) {
1589                 case ExtendedClrTypeCode.Invalid:       throw ADP.UnknownDataType( value.GetType() );
1590                 case ExtendedClrTypeCode.Boolean:       SetBoolean_Unchecked( sink, setters, ordinal, (Boolean) value ); break;
1591                 case ExtendedClrTypeCode.Byte:          SetByte_Unchecked( sink, setters, ordinal, (Byte) value ); break;
1592                 case ExtendedClrTypeCode.Char: {
1593                     char[] charsValue = new char[] {(char) value};
1594                     // recur with array type
1595                     SetCompatibleValue( sink, setters, ordinal, metaData, charsValue, ExtendedClrTypeCode.CharArray, 0 );
1596                     break;
1597                 }
1598                 case ExtendedClrTypeCode.DateTime:      SetDateTime_Checked( sink, setters, ordinal, metaData, (DateTime)value ); break;
1599                 case ExtendedClrTypeCode.DBNull:        SetDBNull_Unchecked( sink, setters, ordinal ); break;
1600                 case ExtendedClrTypeCode.Decimal:       SetDecimal_PossiblyMoney( sink, setters, ordinal, metaData, (Decimal) value ); break;
1601                 case ExtendedClrTypeCode.Double:        SetDouble_Unchecked( sink, setters, ordinal, (Double) value ); break;
1602                 case ExtendedClrTypeCode.Empty:         SetDBNull_Unchecked( sink, setters, ordinal ); break;
1603                 case ExtendedClrTypeCode.Int16:         SetInt16_Unchecked( sink, setters, ordinal, (Int16) value ); break;
1604                 case ExtendedClrTypeCode.Int32:         SetInt32_Unchecked( sink, setters, ordinal, (Int32) value ); break;
1605                 case ExtendedClrTypeCode.Int64:         SetInt64_Unchecked( sink, setters, ordinal, (Int64) value ); break;
1606                 case ExtendedClrTypeCode.SByte:         throw ADP.InvalidCast();
1607                 case ExtendedClrTypeCode.Single:        SetSingle_Unchecked( sink, setters, ordinal, (Single) value ); break;
1608                 case ExtendedClrTypeCode.String:        SetString_LengthChecked( sink, setters, ordinal, metaData, (string) value, offset ); break;
1609                 case ExtendedClrTypeCode.UInt16:        throw ADP.InvalidCast();
1610                 case ExtendedClrTypeCode.UInt32:        throw ADP.InvalidCast();
1611                 case ExtendedClrTypeCode.UInt64:        throw ADP.InvalidCast();
1612                 case ExtendedClrTypeCode.Object:        SetUdt_LengthChecked( sink, setters, ordinal, metaData, value ); break;
1613                 case ExtendedClrTypeCode.ByteArray:     SetByteArray_LengthChecked( sink, setters, ordinal, metaData, (byte[]) value, offset );  break;
1614                 case ExtendedClrTypeCode.CharArray:     SetCharArray_LengthChecked( sink, setters, ordinal, metaData, (char[]) value, offset ); break;
1615                 case ExtendedClrTypeCode.Guid:          SetGuid_Unchecked( sink, setters, ordinal, (Guid) value ); break;
1616                 case ExtendedClrTypeCode.SqlBinary:     SetSqlBinary_LengthChecked( sink, setters, ordinal, metaData, (SqlBinary) value, offset ); break;
1617                 case ExtendedClrTypeCode.SqlBoolean:    SetSqlBoolean_Unchecked( sink, setters, ordinal, (SqlBoolean) value ); break;
1618                 case ExtendedClrTypeCode.SqlByte:       SetSqlByte_Unchecked( sink, setters, ordinal, (SqlByte) value ); break;
1619                 case ExtendedClrTypeCode.SqlDateTime:   SetSqlDateTime_Checked( sink, setters, ordinal, metaData, (SqlDateTime) value ); break;
1620                 case ExtendedClrTypeCode.SqlDouble:     SetSqlDouble_Unchecked( sink, setters, ordinal, (SqlDouble) value ); break;
1621                 case ExtendedClrTypeCode.SqlGuid:       SetSqlGuid_Unchecked( sink, setters, ordinal, (SqlGuid) value ); break;
1622                 case ExtendedClrTypeCode.SqlInt16:      SetSqlInt16_Unchecked( sink, setters, ordinal, (SqlInt16) value ); break;
1623                 case ExtendedClrTypeCode.SqlInt32:      SetSqlInt32_Unchecked( sink, setters, ordinal, (SqlInt32) value ); break;
1624                 case ExtendedClrTypeCode.SqlInt64:      SetSqlInt64_Unchecked( sink, setters, ordinal, (SqlInt64) value ); break;
1625                 case ExtendedClrTypeCode.SqlMoney:      SetSqlMoney_Checked( sink, setters, ordinal, metaData, (SqlMoney) value ); break;
1626                 case ExtendedClrTypeCode.SqlDecimal:    SetSqlDecimal_Unchecked( sink, setters, ordinal, (SqlDecimal) value ); break;
1627                 case ExtendedClrTypeCode.SqlSingle:     SetSqlSingle_Unchecked( sink, setters, ordinal, (SqlSingle) value ); break;
1628                 case ExtendedClrTypeCode.SqlString:     SetSqlString_LengthChecked( sink, setters, ordinal, metaData, (SqlString) value, offset ); break;
1629                 case ExtendedClrTypeCode.SqlChars:      SetSqlChars_LengthChecked( sink, setters, ordinal, metaData, (SqlChars) value, offset ); break;
1630                 case ExtendedClrTypeCode.SqlBytes:      SetSqlBytes_LengthChecked( sink, setters, ordinal, metaData, (SqlBytes) value, offset ); break;
1631                 case ExtendedClrTypeCode.SqlXml:        SetSqlXml_Unchecked( sink, setters, ordinal, (SqlXml) value ); break;
1632                 case ExtendedClrTypeCode.Stream:        SetStream_Unchecked(sink, setters, ordinal, metaData, (StreamDataFeed) value); break;
1633                 case ExtendedClrTypeCode.TextReader:    SetTextReader_Unchecked(sink, setters, ordinal, metaData, (TextDataFeed) value); break;
1634                 case ExtendedClrTypeCode.XmlReader:     SetXmlReader_Unchecked(sink, setters, ordinal, ((XmlDataFeed) value)._source); break;
1635                 default:
1636                     Debug.Assert( false, "Unvalidated extendedtypecode: " + typeCode );
1637                     break;
1638             }
1639         }
1640
1641         // VSTFDevDiv#479681 - Data corruption when sending Katmai Date types to the server via TVP
1642         // Ensures proper handling on DateTime2 sub type for Sql_Variants and TVPs.
1643         internal static void SetCompatibleValueV200(
1644             SmiEventSink_Default sink,
1645             SmiTypedGetterSetter setters,
1646             int ordinal,
1647             SmiMetaData metaData,
1648             object value,
1649             ExtendedClrTypeCode typeCode,
1650             int offset,
1651             int length,
1652             ParameterPeekAheadValue peekAhead,
1653             SqlBuffer.StorageType storageType
1654             )
1655         {
1656             // Ensure caller validated compatibility for types handled directly in this method
1657             Debug.Assert((ExtendedClrTypeCode.DataTable != typeCode &&
1658                             ExtendedClrTypeCode.DbDataReader != typeCode &&
1659                             ExtendedClrTypeCode.IEnumerableOfSqlDataRecord != typeCode) ||
1660                         CanAccessSetterDirectly(metaData, typeCode), "Un-validated type '" + typeCode + "' for metaData: " + metaData.SqlDbType);
1661
1662             if (typeCode == ExtendedClrTypeCode.DateTime)
1663             {
1664                 if (storageType == SqlBuffer.StorageType.DateTime2)
1665                     SetDateTime2_Checked(sink, setters, ordinal, metaData, (DateTime)value);
1666                 else if (storageType == SqlBuffer.StorageType.Date)
1667                     SetDate_Checked(sink, setters, ordinal, metaData, (DateTime)value);
1668                 else
1669                     SetDateTime_Checked(sink, setters, ordinal, metaData, (DateTime)value);
1670             }
1671             else
1672             {
1673                 SetCompatibleValueV200(sink, setters, ordinal, metaData, value, typeCode, offset, length, peekAhead);
1674             }
1675         }
1676
1677         //  Implements SqlClient 2.0-compatible SetValue() semantics + Orcas extensions
1678         //      Assumes caller already validated basic type against the metadata, other than trimming lengths and 
1679         //      checking individual field values (TVPs)
1680         internal static void SetCompatibleValueV200(
1681             SmiEventSink_Default    sink,
1682             SmiTypedGetterSetter    setters,
1683             int                     ordinal,
1684             SmiMetaData             metaData,
1685             object                  value,
1686             ExtendedClrTypeCode     typeCode,
1687             int                     offset,
1688             int                     length,
1689             ParameterPeekAheadValue peekAhead
1690             ) {
1691             // Ensure caller validated compatibility for types handled directly in this method
1692             Debug.Assert(  (ExtendedClrTypeCode.DataTable != typeCode &&
1693                             ExtendedClrTypeCode.DbDataReader != typeCode &&
1694                             ExtendedClrTypeCode.IEnumerableOfSqlDataRecord != typeCode) ||
1695                         CanAccessSetterDirectly(metaData, typeCode), "Un-validated type '" + typeCode + "' for metaData: " + metaData.SqlDbType);
1696
1697             switch(typeCode) {
1698                 case ExtendedClrTypeCode.DataTable:         
1699                     SetDataTable_Unchecked(sink, setters, ordinal, metaData, (DataTable)value); 
1700                     break;
1701                 case ExtendedClrTypeCode.DbDataReader:      
1702                     SetDbDataReader_Unchecked(sink, setters, ordinal, metaData, (DbDataReader)value); 
1703                     break;
1704                 case ExtendedClrTypeCode.IEnumerableOfSqlDataRecord:
1705                     SetIEnumerableOfSqlDataRecord_Unchecked(sink, setters, ordinal, metaData, (IEnumerable<SqlDataRecord>)value, peekAhead); 
1706                     break;
1707                 case ExtendedClrTypeCode.TimeSpan:
1708                     SetTimeSpan_Checked(sink, setters, ordinal, metaData, (TimeSpan)value);
1709                     break;
1710                 case ExtendedClrTypeCode.DateTimeOffset:
1711                     SetDateTimeOffset_Unchecked(sink, setters, ordinal, (DateTimeOffset)value);
1712                     break;
1713                 default:
1714                     SetCompatibleValue(sink, setters, ordinal, metaData, value, typeCode, offset);
1715                     break;
1716             }
1717         }
1718
1719         // Copy multiple fields from reader to ITypedSettersV3
1720         //  Assumes caller enforces that reader and setter metadata are compatible
1721         internal static void FillCompatibleITypedSettersFromReader( SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataReader reader ) {
1722             for ( int i = 0; i < metaData.Length; i++ ) {
1723                 if ( reader.IsDBNull(i) ) {
1724                     ValueUtilsSmi.SetDBNull_Unchecked( sink, setters, i );
1725                 }
1726                 else {
1727                     switch ( metaData[i].SqlDbType ) {
1728                         case SqlDbType.BigInt:
1729                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Int64 ) );
1730                             ValueUtilsSmi.SetInt64_Unchecked( sink, setters, i, reader.GetInt64(i) );
1731                             break;
1732                         case SqlDbType.Binary:
1733                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
1734                             ValueUtilsSmi.SetSqlBytes_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0 );
1735                             break;
1736                         case SqlDbType.Bit:
1737                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Boolean ) );
1738                             SetBoolean_Unchecked( sink, setters, i, reader.GetBoolean(i) );
1739                             break;
1740                         case SqlDbType.Char:
1741                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlChars ) );
1742                             SetSqlChars_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlChars(i), 0 );
1743                             break;
1744                         case SqlDbType.DateTime:
1745                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.DateTime ) );
1746                             SetDateTime_Checked( sink, setters, i, metaData[i], reader.GetDateTime(i) );
1747                             break;
1748                         case SqlDbType.Decimal:
1749                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlDecimal ) );
1750                             SetSqlDecimal_Unchecked( sink, setters, i, reader.GetSqlDecimal(i) );
1751                             break;
1752                         case SqlDbType.Float:
1753                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Double ) );
1754                             SetDouble_Unchecked( sink, setters, i, reader.GetDouble(i) );
1755                             break;
1756                         case SqlDbType.Image:
1757                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
1758                             SetSqlBytes_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0 );
1759                             break;
1760                         case SqlDbType.Int:
1761                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Int32 ) );
1762                             SetInt32_Unchecked( sink, setters, i, reader.GetInt32(i) );
1763                             break;
1764                         case SqlDbType.Money:
1765                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlMoney ) );
1766                             SetSqlMoney_Unchecked( sink, setters, i, metaData[i], reader.GetSqlMoney(i) );
1767                             break;
1768                         case SqlDbType.NChar:
1769                         case SqlDbType.NText:
1770                         case SqlDbType.NVarChar:
1771                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlChars ) );
1772                             SetSqlChars_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlChars(i), 0 );
1773                             break;
1774                         case SqlDbType.Real:
1775                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Single ) );
1776                             SetSingle_Unchecked( sink, setters, i, reader.GetFloat(i) );
1777                             break;
1778                         case SqlDbType.UniqueIdentifier:
1779                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Guid ) );
1780                             SetGuid_Unchecked( sink, setters, i, reader.GetGuid(i) );
1781                             break;
1782                         case SqlDbType.SmallDateTime:
1783                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.DateTime ) );
1784                             SetDateTime_Checked( sink, setters, i, metaData[i], reader.GetDateTime(i) );
1785                             break;
1786                         case SqlDbType.SmallInt:
1787                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Int16 ) );
1788                             SetInt16_Unchecked( sink, setters, i, reader.GetInt16(i) );
1789                             break;
1790                         case SqlDbType.SmallMoney:
1791                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlMoney ) );
1792                             SetSqlMoney_Checked( sink, setters, i, metaData[i], reader.GetSqlMoney(i) );
1793                             break;
1794                         case SqlDbType.Text:
1795                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlChars ) );
1796                             SetSqlChars_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlChars(i), 0 );
1797                             break;
1798                         case SqlDbType.Timestamp:
1799                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
1800                             SetSqlBytes_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0 );
1801                             break;
1802                         case SqlDbType.TinyInt:
1803                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Byte ) );
1804                             SetByte_Unchecked( sink, setters, i, reader.GetByte(i) );
1805                             break;
1806                         case SqlDbType.VarBinary:
1807                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
1808                             SetSqlBytes_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0 );
1809                             break;
1810                         case SqlDbType.VarChar:
1811                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.String ) );
1812                             SetSqlChars_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlChars(i), 0 );
1813                             break;
1814                         case SqlDbType.Xml:
1815                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlXml ) );
1816                             SetSqlXml_Unchecked( sink, setters, i, reader.GetSqlXml(i) );
1817                             break;
1818                         case SqlDbType.Variant:
1819                             object o = reader.GetSqlValue(i);
1820                             ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode( o );
1821                             SetCompatibleValue( sink, setters, i, metaData[i], o, typeCode, 0 );
1822                             break;
1823                             
1824                         case SqlDbType.Udt:
1825                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
1826                             SetSqlBytes_LengthChecked( sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0 );
1827                             break;
1828
1829                         default:
1830                             // In order for us to get here we would have to have an 
1831                             // invalid instance of SqlDbType, or one would have to add 
1832                             // new member to SqlDbType without adding a case in this 
1833                             // switch, hence the assert - it must be bug in our code 
1834                             // not invalid user parameters.
1835                             Debug.Assert( false, "unsupported DbType:" + metaData[i].SqlDbType.ToString() );
1836                             throw ADP.NotSupported();
1837                             
1838                     }
1839                 }
1840             }
1841         }
1842
1843         // Copy multiple fields from reader to SmiTypedGetterSetter
1844         //  Supports V200 code path, without damaging backward compat for V100 code.
1845         //  Main differences are supporting DbDataReader, and for binary, character, decimal and Udt types.
1846         //  Assumes caller enforces that reader and setter metadata are compatible
1847         internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, IList<SmiExtendedMetaData> metaData, DbDataReader reader) {
1848             for (int i = 0; i < metaData.Count; i++) {
1849                 if (reader.IsDBNull(i)) {
1850                     ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i);
1851                 }
1852                 else {
1853                     switch (metaData[i].SqlDbType) {
1854                         case SqlDbType.BigInt:
1855                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64));
1856                             SetInt64_Unchecked(sink, setters, i, reader.GetInt64(i));
1857                             break;
1858                         case SqlDbType.Binary:
1859                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray));
1860                             SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0);
1861                             break;
1862                         case SqlDbType.Bit:
1863                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean));
1864                             SetBoolean_Unchecked(sink, setters, i, reader.GetBoolean(i));
1865                             break;
1866                         case SqlDbType.Char:
1867                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray));
1868                             SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0);
1869                             break;
1870                         case SqlDbType.DateTime:
1871                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime));
1872                             SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i));
1873                             break;
1874                         case SqlDbType.Decimal: { // block to scope sqlReader local to avoid conflicts
1875                                 Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal));
1876                                 // Support full fidelity for SqlDataReader
1877                                 SqlDataReader sqlReader = reader as SqlDataReader;
1878                                 if (null != sqlReader) {
1879                                     SetSqlDecimal_Unchecked(sink, setters, i, sqlReader.GetSqlDecimal(i));
1880                                 }
1881                                 else {
1882                                     SetSqlDecimal_Unchecked(sink, setters, i, new SqlDecimal(reader.GetDecimal(i)));
1883                                 }
1884                             }
1885                             break;
1886                         case SqlDbType.Float:
1887                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double));
1888                             SetDouble_Unchecked(sink, setters, i, reader.GetDouble(i));
1889                             break;
1890                         case SqlDbType.Image:
1891                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray));
1892                             SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0);
1893                             break;
1894                         case SqlDbType.Int:
1895                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32));
1896                             SetInt32_Unchecked(sink, setters, i, reader.GetInt32(i));
1897                             break;
1898                         case SqlDbType.Money:
1899                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney));
1900                             SetSqlMoney_Checked(sink, setters, i, metaData[i], new SqlMoney(reader.GetDecimal(i)));
1901                             break;
1902                         case SqlDbType.NChar:
1903                         case SqlDbType.NText:
1904                         case SqlDbType.NVarChar:
1905                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray));
1906                             SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0);
1907                             break;
1908                         case SqlDbType.Real:
1909                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single));
1910                             SetSingle_Unchecked(sink, setters, i, reader.GetFloat(i));
1911                             break;
1912                         case SqlDbType.UniqueIdentifier:
1913                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid));
1914                             SetGuid_Unchecked(sink, setters, i, reader.GetGuid(i));
1915                             break;
1916                         case SqlDbType.SmallDateTime:
1917                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime));
1918                             SetDateTime_Checked(sink, setters, i,metaData[i], reader.GetDateTime(i));
1919                             break;
1920                         case SqlDbType.SmallInt:
1921                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16));
1922                             SetInt16_Unchecked(sink, setters, i, reader.GetInt16(i));
1923                             break;
1924                         case SqlDbType.SmallMoney:
1925                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney));
1926                             SetSqlMoney_Checked(sink, setters, i, metaData[i], new SqlMoney(reader.GetDecimal(i)));
1927                             break;
1928                         case SqlDbType.Text:
1929                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray));
1930                             SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0);
1931                             break;
1932                         case SqlDbType.Timestamp:
1933                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray));
1934                             SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0);
1935                             break;
1936                         case SqlDbType.TinyInt:
1937                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte));
1938                             SetByte_Unchecked(sink, setters, i, reader.GetByte(i));
1939                             break;
1940                         case SqlDbType.VarBinary:
1941                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray));
1942                             SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0);
1943                             break;
1944                         case SqlDbType.VarChar:
1945                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String));
1946                             SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0);
1947                             break;
1948                         case SqlDbType.Xml: {
1949                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml));
1950                                 SqlDataReader sqlReader = reader as SqlDataReader;
1951                                 if (null != sqlReader) {
1952                                     SetSqlXml_Unchecked(sink, setters, i, sqlReader.GetSqlXml(i));
1953                                 }
1954                                 else {
1955                                     SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0);
1956                                 }
1957                             }
1958                             break;
1959                         case SqlDbType.Variant: {  // block to scope sqlReader local and avoid conflicts
1960                                 // Support better options for SqlDataReader
1961                                 SqlDataReader sqlReader = reader as SqlDataReader;
1962                                 SqlBuffer.StorageType storageType = SqlBuffer.StorageType.Empty;
1963                                 object o;
1964                                 if (null != sqlReader) {
1965                                     o = sqlReader.GetSqlValue(i);
1966                                     storageType = sqlReader.GetVariantInternalStorageType(i);
1967                                 }
1968                                 else {
1969                                     o = reader.GetValue(i);
1970                                 }
1971                                 ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null,
1972                                     // 
1973
1974                                     SmiContextFactory.KatmaiVersion
1975                                     );
1976                                 if ((storageType == SqlBuffer.StorageType.DateTime2) || (storageType == SqlBuffer.StorageType.Date))
1977                                     SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null, storageType);
1978                                 else
1979                                     SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null);
1980                             }
1981                             break;
1982
1983                         case SqlDbType.Udt:
1984                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray));
1985                             // Skip serialization for Udt types.
1986                             SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0);
1987                             break;
1988
1989                         // SqlDbType.Structured should have been caught before this point for TVPs.  SUDTs will still need to implement.
1990
1991                         case SqlDbType.Date:
1992                         case SqlDbType.DateTime2:
1993                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime));
1994                             SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i));
1995                             break;
1996                         case SqlDbType.Time: { // block to scope sqlReader local and avoid conflicts
1997                                 Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan));
1998                                 SqlDataReader sqlReader = reader as SqlDataReader;
1999                                 TimeSpan ts;
2000                                 if (null != sqlReader) {
2001                                     ts = sqlReader.GetTimeSpan(i);
2002                                 } else {
2003                                     ts = (TimeSpan)reader.GetValue(i);
2004                                 }
2005                                 SetTimeSpan_Checked(sink, setters, i, metaData[i], ts);
2006                             }
2007                             break;
2008                         case SqlDbType.DateTimeOffset: { // block to scope sqlReader local and avoid conflicts
2009                                 Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset));
2010                                 SqlDataReader sqlReader = reader as SqlDataReader;
2011                                 DateTimeOffset dto;
2012                                 if (null != sqlReader) {
2013                                     dto = sqlReader.GetDateTimeOffset(i);
2014                                 } else {
2015                                     dto = (DateTimeOffset)reader.GetValue(i);
2016                                 }
2017                                 SetDateTimeOffset_Unchecked(sink, setters, i, dto);
2018                             }
2019                             break;
2020
2021                         default:
2022                             // In order for us to get here we would have to have an 
2023                             // invalid instance of SqlDbType, or one would have to add 
2024                             // new member to SqlDbType without adding a case in this 
2025                             // switch, hence the assert - it must be bug in our code 
2026                             // not invalid user parameters.
2027                             Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString());
2028                             throw ADP.NotSupported();
2029
2030                     }
2031                 }
2032             }
2033         }
2034
2035         internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record) {
2036             FillCompatibleITypedSettersFromRecord(sink, setters, metaData, record, null);
2037         }
2038
2039         internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) {
2040             for (int i = 0; i < metaData.Length; ++i) {
2041                 if (null != useDefaultValues && useDefaultValues[i]) {
2042                     continue;
2043                 }
2044                 if (record.IsDBNull(i)) {
2045                     ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i);
2046                 } else {
2047                     switch (metaData[i].SqlDbType) {
2048                         case SqlDbType.BigInt:
2049                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Int64 ) );
2050                             SetInt64_Unchecked( sink, setters, i, record.GetInt64(i) );
2051                             break;
2052                         case SqlDbType.Binary:
2053                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
2054                             SetBytes_FromRecord( sink, setters, i, metaData[i], record, 0 );
2055                             break;
2056                         case SqlDbType.Bit:
2057                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Boolean ) );
2058                             SetBoolean_Unchecked( sink, setters, i, record.GetBoolean(i) );
2059                             break;
2060                         case SqlDbType.Char:
2061                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlChars ) );
2062                             SetChars_FromRecord( sink, setters, i, metaData[i], record, 0 );
2063                             break;
2064                         case SqlDbType.DateTime:
2065                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.DateTime ) );
2066                             SetDateTime_Checked( sink, setters, i, metaData[i], record.GetDateTime(i) );
2067                             break;
2068                         case SqlDbType.Decimal:
2069                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlDecimal ) );
2070                             SetSqlDecimal_Unchecked( sink, setters, i, record.GetSqlDecimal(i) );
2071                             break;
2072                         case SqlDbType.Float:
2073                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Double ) );
2074                             SetDouble_Unchecked( sink, setters, i, record.GetDouble(i) );
2075                             break;
2076                         case SqlDbType.Image:
2077                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
2078                             SetBytes_FromRecord( sink, setters, i, metaData[i], record, 0 );
2079                             break;
2080                         case SqlDbType.Int:
2081                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Int32 ) );
2082                             SetInt32_Unchecked( sink, setters, i, record.GetInt32(i) );
2083                             break;
2084                         case SqlDbType.Money:
2085                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlMoney ) );
2086                             SetSqlMoney_Unchecked( sink, setters, i, metaData[i], record.GetSqlMoney(i) );
2087                             break;
2088                         case SqlDbType.NChar:
2089                         case SqlDbType.NText:
2090                         case SqlDbType.NVarChar:
2091                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlChars ) );
2092                             SetChars_FromRecord( sink, setters, i, metaData[i], record, 0 );
2093                             break;
2094                         case SqlDbType.Real:
2095                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Single ) );
2096                             SetSingle_Unchecked( sink, setters, i, record.GetFloat(i) );
2097                             break;
2098                         case SqlDbType.UniqueIdentifier:
2099                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Guid ) );
2100                             SetGuid_Unchecked( sink, setters, i, record.GetGuid(i) );
2101                             break;
2102                         case SqlDbType.SmallDateTime:
2103                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.DateTime ) );
2104                             SetDateTime_Checked( sink, setters, i, metaData[i], record.GetDateTime(i) );
2105                             break;
2106                         case SqlDbType.SmallInt:
2107                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Int16 ) );
2108                             SetInt16_Unchecked( sink, setters, i, record.GetInt16(i) );
2109                             break;
2110                         case SqlDbType.SmallMoney:
2111                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlMoney ) );
2112                             SetSqlMoney_Checked( sink, setters, i, metaData[i], record.GetSqlMoney(i) );
2113                             break;
2114                         case SqlDbType.Text:
2115                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlChars ) );
2116                             SetChars_FromRecord( sink, setters, i, metaData[i], record, 0 );
2117                             break;
2118                         case SqlDbType.Timestamp:
2119                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
2120                             SetBytes_FromRecord( sink, setters, i, metaData[i], record, 0 );
2121                             break;
2122                         case SqlDbType.TinyInt:
2123                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.Byte ) );
2124                             SetByte_Unchecked( sink, setters, i, record.GetByte(i) );
2125                             break;
2126                         case SqlDbType.VarBinary:
2127                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
2128                             SetBytes_FromRecord( sink, setters, i, metaData[i], record, 0 );
2129                             break;
2130                         case SqlDbType.VarChar:
2131                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.String ) );
2132                             SetChars_FromRecord( sink, setters, i, metaData[i], record, 0 );
2133                             break;
2134                         case SqlDbType.Xml:
2135                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlXml ) );
2136                             SetSqlXml_Unchecked( sink, setters, i, record.GetSqlXml(i) );    // perf improvement?
2137                             break;
2138                         case SqlDbType.Variant:
2139                             object o = record.GetSqlValue(i);
2140                             ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode( o );
2141                             SetCompatibleValue( sink, setters, i, metaData[i], o, typeCode, 0 );
2142                             break;
2143                         case SqlDbType.Udt:
2144                             Debug.Assert( CanAccessSetterDirectly( metaData[i], ExtendedClrTypeCode.SqlBytes ) );
2145                             SetBytes_FromRecord( sink, setters, i, metaData[i], record, 0 );
2146                             break;
2147                         default:
2148                             Debug.Assert( false, "unsupported DbType:" + metaData[i].SqlDbType.ToString() );
2149                             throw ADP.NotSupported();
2150                     }
2151                 }
2152             }
2153         }
2154
2155         internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, SmiTypedGetterSetter setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues)
2156         {
2157             for (int i = 0; i < metaData.Length; ++i)
2158             {
2159                 if (null != useDefaultValues && useDefaultValues[i])
2160                 {
2161                     continue;
2162                 }
2163                 if (record.IsDBNull(i))
2164                 {
2165                     ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i);
2166                 }
2167                 else
2168                 {
2169                     switch (metaData[i].SqlDbType)
2170                     {
2171                         case SqlDbType.BigInt:
2172                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64));
2173                             SetInt64_Unchecked(sink, setters, i, record.GetInt64(i));
2174                             break;
2175                         case SqlDbType.Binary:
2176                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes));
2177                             SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0);
2178                             break;
2179                         case SqlDbType.Bit:
2180                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean));
2181                             SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i));
2182                             break;
2183                         case SqlDbType.Char:
2184                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars));
2185                             SetChars_FromRecord(sink, setters, i, metaData[i], record, 0);
2186                             break;
2187                         case SqlDbType.DateTime:
2188                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime));
2189                             SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i));
2190                             break;
2191                         case SqlDbType.Decimal:
2192                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal));
2193                             SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i));
2194                             break;
2195                         case SqlDbType.Float:
2196                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double));
2197                             SetDouble_Unchecked(sink, setters, i, record.GetDouble(i));
2198                             break;
2199                         case SqlDbType.Image:
2200                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes));
2201                             SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0);
2202                             break;
2203                         case SqlDbType.Int:
2204                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32));
2205                             SetInt32_Unchecked(sink, setters, i, record.GetInt32(i));
2206                             break;
2207                         case SqlDbType.Money:
2208                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney));
2209                             SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i));
2210                             break;
2211                         case SqlDbType.NChar:
2212                         case SqlDbType.NText:
2213                         case SqlDbType.NVarChar:
2214                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars));
2215                             SetChars_FromRecord(sink, setters, i, metaData[i], record, 0);
2216                             break;
2217                         case SqlDbType.Real:
2218                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single));
2219                             SetSingle_Unchecked(sink, setters, i, record.GetFloat(i));
2220                             break;
2221                         case SqlDbType.UniqueIdentifier:
2222                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid));
2223                             SetGuid_Unchecked(sink, setters, i, record.GetGuid(i));
2224                             break;
2225                         case SqlDbType.SmallDateTime:
2226                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime));
2227                             SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i));
2228                             break;
2229                         case SqlDbType.SmallInt:
2230                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16));
2231                             SetInt16_Unchecked(sink, setters, i, record.GetInt16(i));
2232                             break;
2233                         case SqlDbType.SmallMoney:
2234                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney));
2235                             SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i));
2236                             break;
2237                         case SqlDbType.Text:
2238                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars));
2239                             SetChars_FromRecord(sink, setters, i, metaData[i], record, 0);
2240                             break;
2241                         case SqlDbType.Timestamp:
2242                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes));
2243                             SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0);
2244                             break;
2245                         case SqlDbType.TinyInt:
2246                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte));
2247                             SetByte_Unchecked(sink, setters, i, record.GetByte(i));
2248                             break;
2249                         case SqlDbType.VarBinary:
2250                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes));
2251                             SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0);
2252                             break;
2253                         case SqlDbType.VarChar:
2254                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String));
2255                             SetChars_FromRecord(sink, setters, i, metaData[i], record, 0);
2256                             break;
2257                         case SqlDbType.Xml:
2258                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml));
2259                             SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i));    // perf improvement?
2260                             break;
2261                         case SqlDbType.Variant:
2262                             object o = record.GetSqlValue(i);
2263                             ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o);
2264                             SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, -1 /* no length restriction */, null /* no peekahead */);
2265                             break;
2266                         case SqlDbType.Udt:
2267                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes));
2268                             SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0);
2269                             break;
2270                         case SqlDbType.Date:
2271                         case SqlDbType.DateTime2:
2272                             Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime));
2273                             SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i));
2274                             break;
2275                         case SqlDbType.Time:
2276                             { // block to scope sqlReader local and avoid conflicts
2277                                 Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan));
2278                                 SqlDataRecord sqlRecord = record as SqlDataRecord;
2279                                 TimeSpan ts;
2280                                 if (null != sqlRecord)
2281                                 {
2282                                     ts = sqlRecord.GetTimeSpan(i);
2283                                 }
2284                                 else
2285                                 {
2286                                     ts = (TimeSpan)record.GetValue(i);
2287                                 }
2288                                 SetTimeSpan_Checked(sink, setters, i, metaData[i], ts);
2289                             }
2290                             break;
2291                         case SqlDbType.DateTimeOffset:
2292                             { // block to scope sqlReader local and avoid conflicts
2293                                 Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset));
2294                                 SqlDataRecord sqlRecord = record as SqlDataRecord;
2295                                 DateTimeOffset dto;
2296                                 if (null != sqlRecord)
2297                                 {
2298                                     dto = sqlRecord.GetDateTimeOffset(i);
2299                                 }
2300                                 else
2301                                 {
2302                                     dto = (DateTimeOffset)record.GetValue(i);
2303                                 }
2304                                 SetDateTimeOffset_Unchecked(sink, setters, i, dto);
2305                             }
2306                             break;
2307
2308                         default:
2309                             Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString());
2310                             throw ADP.NotSupported();
2311                     }
2312                 }
2313             }
2314         }
2315
2316         // spool a Stream into a scratch stream from the Smi interface and return it as a Stream
2317         internal static Stream CopyIntoNewSmiScratchStream( Stream source, SmiEventSink_Default sink, SmiContext context )  {
2318             Stream dest;
2319             if (null == context) {
2320                 dest = new MemoryStream();
2321             }
2322             else {
2323                 dest = new SqlClientWrapperSmiStream( sink, context.GetScratchStream( sink ) );
2324             }
2325
2326             int chunkSize;
2327             if ( source.CanSeek && __maxByteChunkSize > source.Length ) {
2328                 chunkSize = unchecked( (int) source.Length );  // unchecked cast is safe due to check on line above
2329             }
2330             else {
2331                 chunkSize = __maxByteChunkSize;
2332             }
2333
2334             byte[] copyBuffer = new byte[chunkSize];
2335             int bytesRead;
2336             while ( 0 != ( bytesRead = source.Read( copyBuffer, 0, chunkSize ) ) ) {
2337                 dest.Write( copyBuffer, 0, bytesRead );
2338             }
2339             dest.Flush();
2340
2341             // SQLBU 494334
2342             //  Need to re-wind scratch stream to beginning before returning
2343             dest.Seek(0, SeekOrigin.Begin);
2344
2345             return dest;
2346         }
2347
2348         // spool a Stream into a scratch stream from the Smi interface and return it as a SqlStreamChars
2349         internal static SqlStreamChars CopyIntoNewSmiScratchStreamChars( Stream source, SmiEventSink_Default sink, SmiContext context )  {
2350             SqlClientWrapperSmiStreamChars dest = new SqlClientWrapperSmiStreamChars( sink, context.GetScratchStream( sink ) );
2351
2352             int chunkSize;
2353             if ( source.CanSeek && __maxByteChunkSize > source.Length ) {
2354                 chunkSize = unchecked( (int) source.Length );  // unchecked cast is safe due to check on line above
2355             }
2356             else {
2357                 chunkSize = __maxByteChunkSize;
2358             }
2359
2360             byte[] copyBuffer = new byte[chunkSize];
2361             int bytesRead;
2362             while ( 0 != ( bytesRead = source.Read( copyBuffer, 0, chunkSize ) ) ) {
2363                 dest.Write( copyBuffer, 0, bytesRead );
2364             }
2365             dest.Flush();
2366
2367             // SQLBU 494334
2368             //  Need to re-wind scratch stream to beginning before returning
2369             dest.Seek(0, SeekOrigin.Begin);
2370
2371             return dest;
2372         }
2373
2374     //
2375     //  Common utility code to get lengths correct for trimming
2376     //
2377         private static object GetUdt_LengthChecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
2378             object result;
2379             if (IsDBNull_Unchecked(sink, getters, ordinal)) {
2380                 Type t = metaData.Type;
2381                 Debug.Assert(t != null, "Unexpected null of udtType on GetUdt_LengthChecked!");
2382                 result = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[]{}, CultureInfo.InvariantCulture);
2383                 Debug.Assert(result != null);
2384             }
2385             else {
2386                 // Note: do not need to copy getter stream, since it will not be used beyond
2387                 //  deserialization (valid lifetime of getters is limited).
2388                 Stream s = new SmiGettersStream( sink, getters, ordinal, metaData );
2389                 result = SerializationHelperSql9.Deserialize( s, metaData.Type );
2390             }
2391             return result;
2392         }
2393         private static Decimal GetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) {
2394             if (SqlDbType.Decimal == metaData.SqlDbType) {
2395                 return GetSqlDecimal_Unchecked( sink, getters, ordinal ).Value;
2396             }
2397             else {
2398                 Debug.Assert( SqlDbType.Money == metaData.SqlDbType ||
2399                                 SqlDbType.SmallMoney == metaData.SqlDbType, 
2400                             "Unexpected sqldbtype=" + metaData.SqlDbType);
2401                 return GetSqlMoney_Unchecked( sink, getters, ordinal ).Value;
2402             }
2403         }
2404
2405         private static void SetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Decimal value) {
2406             if (SqlDbType.Decimal == metaData.SqlDbType || SqlDbType.Variant == metaData.SqlDbType) {
2407                 SetDecimal_Unchecked( sink, setters, ordinal, value );
2408             }
2409             else {
2410                 Debug.Assert( SqlDbType.Money == metaData.SqlDbType ||
2411                                 SqlDbType.SmallMoney == metaData.SqlDbType, 
2412                             "Unexpected sqldbtype=" + metaData.SqlDbType);
2413                 SetSqlMoney_Checked( sink, setters, ordinal, metaData, new SqlMoney(value) );
2414             }
2415         }
2416
2417         // Hard coding smalldatetime limits...
2418         private static readonly DateTime x_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998);
2419         private static readonly DateTime x_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999);
2420         private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) {
2421             if (SqlDbType.SmallDateTime == dbType && (x_dtSmallMax < value || x_dtSmallMin > value)) {
2422                 throw ADP.InvalidMetaDataValue();
2423             }
2424         }
2425
2426         private static readonly TimeSpan x_timeMin = TimeSpan.Zero;
2427         private static readonly TimeSpan x_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1);
2428         private static void VerifyTimeRange(SqlDbType dbType, TimeSpan value) {
2429             if (SqlDbType.Time == dbType && (x_timeMin > value || value > x_timeMax)) {
2430                 throw ADP.InvalidMetaDataValue();
2431             }
2432         }
2433
2434         private static void SetDateTime_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) {
2435             VerifyDateTimeRange(metaData.SqlDbType, value);
2436             SetDateTime_Unchecked(sink, setters, ordinal, ((SqlDbType.Date == metaData.SqlDbType) ? value.Date : value));
2437         }
2438
2439         private static void SetTimeSpan_Checked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, TimeSpan value) {
2440             VerifyTimeRange(metaData.SqlDbType, value);
2441             SetTimeSpan_Unchecked(sink, setters, ordinal, value);
2442         }
2443
2444         private static void SetSqlDateTime_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDateTime value) {
2445             if (!value.IsNull) {
2446                 VerifyDateTimeRange(metaData.SqlDbType, value.Value);
2447             }
2448             SetSqlDateTime_Unchecked(sink, setters, ordinal, value);
2449         }
2450
2451         private static void SetDateTime2_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value)
2452         {
2453             VerifyDateTimeRange(metaData.SqlDbType, value);
2454             SetDateTime2_Unchecked(sink, setters, ordinal, metaData, value);
2455         }
2456
2457         private static void SetDate_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value)
2458         {
2459             VerifyDateTimeRange(metaData.SqlDbType, value);
2460             SetDate_Unchecked(sink, setters, ordinal, metaData, value);
2461         }
2462
2463         private static void SetSqlMoney_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) {
2464             if (!value.IsNull && SqlDbType.SmallMoney == metaData.SqlDbType) {
2465                 decimal decimalValue = value.Value;
2466                 if (TdsEnums.SQL_SMALL_MONEY_MIN > decimalValue || TdsEnums.SQL_SMALL_MONEY_MAX < decimalValue) {
2467                     throw SQL.MoneyOverflow(decimalValue.ToString(CultureInfo.InvariantCulture));
2468                 }
2469             }
2470             SetSqlMoney_Unchecked(sink, setters, ordinal, metaData, value);
2471         }
2472
2473         private static void SetByteArray_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, byte[] buffer, int offset ) {
2474             int length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, buffer.Length, offset, buffer.Length - offset );
2475             Debug.Assert( length >= 0, "buffer.Length was invalid!" );
2476             SetByteArray_Unchecked( sink, setters, ordinal, buffer, offset, length );
2477         }
2478
2479         private static void SetCharArray_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, char[] buffer, int offset ) {
2480             int length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, buffer.Length, offset, buffer.Length - offset );
2481             Debug.Assert( length >= 0, "buffer.Length was invalid!" );
2482             SetCharArray_Unchecked( sink, setters, ordinal, buffer, offset, length );
2483         }
2484
2485         private static void SetSqlBinary_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBinary value, int offset ) {
2486             int length = 0;
2487             if ( !value.IsNull ) {
2488                 length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, value.Length, offset, value.Length - offset );
2489                 Debug.Assert( length >= 0, "value.Length was invalid!" );
2490             }
2491             SetSqlBinary_Unchecked( sink, setters, ordinal, value, offset, length ); 
2492         }
2493
2494         private static void SetBytes_FromRecord( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset ) {
2495             int length = 0;
2496
2497             // Deal with large values by sending bufferLength of NoLengthLimit (== assume 
2498             //  CheckXetParameters will ignore requested-length checks in this case
2499             long bufferLength = record.GetBytes(ordinal, 0, null, 0, 0);
2500             if ( bufferLength > Int32.MaxValue ) {
2501                 bufferLength = NoLengthLimit;
2502             }
2503             length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked( (int) bufferLength ), offset, checked( (int) bufferLength ) );
2504
2505             int chunkSize;
2506             if ( length > __maxByteChunkSize || length < 0 ) {
2507                 chunkSize = __maxByteChunkSize;
2508             }
2509             else {
2510                 chunkSize = checked( (int)length );
2511             }
2512
2513             byte[] buffer = new byte[ chunkSize ];
2514             long bytesRead;
2515             long bytesWritten = 1;  // prime value to get into write loop
2516             long currentOffset = offset;
2517             long lengthWritten = 0;
2518
2519             while ( (length < 0  || lengthWritten < length) &&
2520                     0 != ( bytesRead = record.GetBytes( ordinal, currentOffset, buffer, 0, chunkSize ) ) &&
2521                     0 != bytesWritten ) {
2522                 bytesWritten = setters.SetBytes( sink, ordinal, currentOffset, buffer, 0, checked( (int) bytesRead ) );
2523                 sink.ProcessMessagesAndThrow();
2524                 checked{ currentOffset += bytesWritten; }
2525                 checked{ lengthWritten += bytesWritten; }
2526             }
2527
2528             // Make sure to trim any left-over data
2529             setters.SetBytesLength( sink, ordinal, currentOffset );
2530             sink.ProcessMessagesAndThrow();
2531         }
2532
2533         private static void SetBytes_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) {
2534             int length = 0;
2535
2536             // Deal with large values by sending bufferLength of NoLengthLimit (== assume 
2537             //  CheckXetParameters will ignore requested-length checks in this case)
2538             length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ );
2539
2540             // Use fixed chunk size for all cases to avoid inquiring from reader.
2541             int chunkSize = __maxByteChunkSize;
2542
2543             byte[] buffer = new byte[ chunkSize ];
2544             long bytesRead;
2545             long bytesWritten = 1;  // prime value to get into write loop
2546             long currentOffset = offset;
2547             long lengthWritten = 0;
2548
2549             while ((length < 0  || lengthWritten < length) &&
2550                     0 != (bytesRead = reader.GetBytes(ordinal, currentOffset, buffer, 0, chunkSize)) &&
2551                     0 != bytesWritten) {
2552                 bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int) bytesRead));
2553                 sink.ProcessMessagesAndThrow();
2554                 checked{ currentOffset += bytesWritten; }
2555                 checked{ lengthWritten += bytesWritten; }
2556             }
2557
2558             // Make sure to trim any left-over data (remember to trim at end of offset, not just the amount written
2559             setters.SetBytesLength(sink, ordinal, currentOffset);
2560             sink.ProcessMessagesAndThrow();
2561         }
2562
2563         private static void SetSqlBytes_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBytes value, int offset ) {
2564             int length = 0;
2565             if ( !value.IsNull ) {
2566                 // Deal with large values by sending bufferLength of NoLengthLimit (== assume 
2567                 //  CheckXetParameters will ignore requested-length checks in this case
2568                 long bufferLength = value.Length;
2569                 if ( bufferLength > Int32.MaxValue ) {
2570                     bufferLength = NoLengthLimit;
2571                 }
2572                 length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked( (int) bufferLength ), offset, checked( (int) bufferLength ) );
2573             }
2574             SetSqlBytes_Unchecked( sink, setters, ordinal, value, 0, length ); 
2575         }
2576
2577         private static void SetChars_FromRecord( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset ) {
2578             int length = 0;
2579
2580             // Deal with large values by sending bufferLength of NoLengthLimit
2581             //  CheckXetParameters will ignore length checks in this case
2582             long bufferLength = record.GetChars(ordinal, 0, null, 0, 0);
2583             if ( bufferLength > Int32.MaxValue ) {
2584                 bufferLength = NoLengthLimit;
2585             }
2586             length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked( (int) bufferLength ), offset, checked( (int) bufferLength - offset ) );
2587
2588             int chunkSize;
2589             if ( length > __maxCharChunkSize || length < 0 ) {
2590                 if (MetaDataUtilsSmi.IsAnsiType(metaData.SqlDbType)) {
2591                     chunkSize = __maxByteChunkSize;
2592                 } else {
2593                     chunkSize = __maxCharChunkSize;
2594                 }
2595             }
2596             else {
2597                 chunkSize = checked( (int)length );
2598             }
2599
2600             char[] buffer = new char[ chunkSize ];
2601             long charsRead;
2602             long charsWritten = 1;  // prime value to get into write loop
2603             long currentOffset = offset;
2604             long lengthWritten = 0;
2605
2606             while ( (length < 0  || lengthWritten < length) &&
2607                     0 != ( charsRead = record.GetChars( ordinal, currentOffset, buffer, 0, chunkSize ) ) &&
2608                     0 != charsWritten ) {
2609                 charsWritten = setters.SetChars( sink, ordinal, currentOffset, buffer, 0, checked( (int) charsRead ) );
2610                 sink.ProcessMessagesAndThrow();
2611                 checked{ currentOffset += charsWritten; }
2612                 checked{ lengthWritten += charsWritten;}
2613             }
2614
2615             // Make sure to trim any left-over data
2616             setters.SetCharsLength( sink, ordinal, currentOffset );
2617             sink.ProcessMessagesAndThrow();
2618         }
2619
2620         // Transfer a character value from a reader when we're not sure which GetXXX method the reader will support.
2621         //  Prefers to chunk data via GetChars, but falls back to GetString if that fails.
2622         //  Mainly put in place because DataTableReader doesn't support GetChars on string columns, but others could fail too...
2623         private static void SetCharsOrString_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) {
2624             bool success = false;
2625             try {
2626                 SetChars_FromReader(sink, setters, ordinal, metaData, reader, offset);
2627                 success = true;
2628             }
2629             catch(Exception e) {
2630                 if (!ADP.IsCatchableExceptionType(e)) {
2631                     throw;
2632                 }
2633             }
2634
2635             if (!success) {
2636                 SetString_FromReader(sink, setters, ordinal, metaData, reader, offset);
2637             }
2638         }
2639
2640         // Use chunking via SetChars to transfer a value from a reader to a gettersetter
2641         private static void SetChars_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) {
2642             int length = 0;
2643
2644             // Deal with large values by sending bufferLength of NoLengthLimit (== assume 
2645             //  CheckXetParameters will ignore requested-length checks in this case)
2646             length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ );
2647
2648             // Use fixed chunk size for all cases to avoid inquiring from reader.
2649             int chunkSize;
2650             if (MetaDataUtilsSmi.IsAnsiType(metaData.SqlDbType)) {
2651                 chunkSize = __maxByteChunkSize;
2652             } else {
2653                 chunkSize = __maxCharChunkSize;
2654             }
2655
2656             char[] buffer = new char[ chunkSize ];
2657             long charsRead;
2658             long charsWritten = 1;  // prime value to get into write loop
2659             long currentOffset = offset;
2660             long lengthWritten = 0;
2661
2662             while ((length < 0  || lengthWritten < length) &&
2663                     0 != (charsRead = reader.GetChars(ordinal, currentOffset, buffer, 0, chunkSize)) &&
2664                     0 != charsWritten) {
2665                 charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int) charsRead));
2666                 sink.ProcessMessagesAndThrow();
2667                 checked{ currentOffset += charsWritten; }
2668                 checked{ lengthWritten += charsWritten; }
2669             }
2670
2671             // Make sure to trim any left-over data (remember to trim at end of offset, not just the amount written
2672             setters.SetCharsLength(sink, ordinal, currentOffset);
2673             sink.ProcessMessagesAndThrow();
2674         }
2675
2676         private static void SetString_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) {
2677             string value = reader.GetString(ordinal);
2678             int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, value.Length, 0, NoLengthLimit /* buffer */, offset, NoLengthLimit /* request */);
2679
2680             setters.SetString(sink, ordinal, value, offset, length);
2681             sink.ProcessMessagesAndThrow();
2682         }
2683
2684         private static void SetSqlChars_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlChars value, int offset ) {
2685             int length = 0;
2686             if ( !value.IsNull ) {
2687                 // Deal with large values by sending bufferLength of NoLengthLimit
2688                 //  CheckXetParameters will ignore length checks in this case
2689                 long bufferLength = value.Length;
2690                 if ( bufferLength > Int32.MaxValue ) {
2691                     bufferLength = NoLengthLimit;
2692                 }
2693                 length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked( (int) bufferLength ), offset, checked( (int) bufferLength - offset ) );
2694             }
2695             SetSqlChars_Unchecked( sink, setters, ordinal, value, 0, length ); 
2696         }
2697
2698         private static void SetSqlString_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset ) {
2699             if ( value.IsNull ) {
2700                 SetDBNull_Unchecked( sink, setters, ordinal );
2701             }
2702             else {
2703                 string stringValue = value.Value;
2704                 int length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, stringValue.Length, offset, stringValue.Length - offset );
2705                 Debug.Assert( length >= 0, "value.Length was invalid!" );
2706                 SetSqlString_Unchecked( sink, setters, ordinal, metaData, value, offset, length );
2707             }
2708         }
2709
2710         private static void SetString_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, string value, int offset ) {
2711             int length = CheckXetParameters( metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, value.Length, offset, checked( value.Length - offset ) );
2712             Debug.Assert( length >= 0, "value.Length was invalid!" );
2713             SetString_Unchecked( sink, setters, ordinal, value, offset, length );
2714         }
2715
2716         private static void SetUdt_LengthChecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, object value ) {
2717             if ( ADP.IsNull( value ) ) {
2718                 setters.SetDBNull( sink, ordinal );
2719                 sink.ProcessMessagesAndThrow();
2720             }
2721             else {
2722                 System.IO.Stream target = new SmiSettersStream( sink, setters, ordinal, metaData );
2723                 SerializationHelperSql9.Serialize( target, value );
2724             }            
2725         }
2726
2727     //
2728     //  Semantics support routines
2729     //
2730
2731         private static void ThrowIfInvalidSetterAccess( SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode ) {
2732             if ( !CanAccessSetterDirectly( metaData, setterTypeCode ) ) {
2733                 throw ADP.InvalidCast();
2734             }
2735         }
2736
2737         private static void ThrowIfITypedGettersIsNull( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
2738             if ( IsDBNull_Unchecked( sink, getters, ordinal ) ) {
2739                 throw SQL.SqlNullValue();
2740             }
2741         }
2742
2743         private static bool CanAccessGetterDirectly( SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode ) {
2744             // Make sure no-one adds new ExtendedType, nor SqlDbType without updating this file!
2745             Debug.Assert( ExtendedClrTypeCode.First == 0 && (int)ExtendedClrTypeCode.Last == __canAccessGetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessGetterDirectly" );
2746             Debug.Assert( SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == __canAccessGetterDirectly.GetLength(1) - 1, "SqlDbType does not match with __canAccessGetterDirectly" );
2747             Debug.Assert( ExtendedClrTypeCode.First <= setterTypeCode && ExtendedClrTypeCode.Last >= setterTypeCode );
2748             Debug.Assert( SqlDbType.BigInt <= metaData.SqlDbType && SqlDbType.DateTimeOffset >= metaData.SqlDbType );
2749
2750             bool returnValue =  __canAccessGetterDirectly[(int)setterTypeCode, (int)metaData.SqlDbType];
2751
2752             // Additional restrictions to distinguish TVPs and Structured UDTs
2753             if (returnValue &&
2754                    (ExtendedClrTypeCode.DataTable == setterTypeCode ||
2755                     ExtendedClrTypeCode.DbDataReader == setterTypeCode ||
2756                     ExtendedClrTypeCode.IEnumerableOfSqlDataRecord == setterTypeCode)) {
2757                 returnValue = metaData.IsMultiValued;
2758             }
2759
2760             return returnValue;
2761         }
2762
2763         private static bool CanAccessSetterDirectly( SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode ) {
2764             // Make sure no-one adds new ExtendedType, nor SqlDbType without updating this file!
2765             Debug.Assert( ExtendedClrTypeCode.First == 0 && (int)ExtendedClrTypeCode.Last == __canAccessSetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessSetterDirectly" );
2766             Debug.Assert( SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == __canAccessSetterDirectly.GetLength(1) - 1, "SqlDbType does not match with __canAccessSetterDirectly" );
2767             Debug.Assert( ExtendedClrTypeCode.First <= setterTypeCode && ExtendedClrTypeCode.Last >= setterTypeCode );
2768             Debug.Assert( SqlDbType.BigInt <= metaData.SqlDbType && SqlDbType.DateTimeOffset >= metaData.SqlDbType );
2769
2770             bool returnValue = __canAccessSetterDirectly[(int)setterTypeCode, (int)metaData.SqlDbType];
2771
2772             // Additional restrictions to distinguish TVPs and Structured UDTs
2773             if (returnValue &&
2774                    (ExtendedClrTypeCode.DataTable == setterTypeCode ||
2775                     ExtendedClrTypeCode.DbDataReader == setterTypeCode ||
2776                     ExtendedClrTypeCode.IEnumerableOfSqlDataRecord == setterTypeCode)) {
2777                 returnValue = metaData.IsMultiValued;
2778             }
2779
2780             return returnValue;
2781         }
2782
2783         private static long PositiveMin(long first, long second) {
2784             if (first < 0) {
2785                 return second;
2786             }
2787
2788             if (second < 0) {
2789                 return first;
2790             }
2791
2792             return Math.Min(first, second);
2793         }
2794
2795         // Check Get Byte/Chars parameters, throw or adjust invalid values
2796         private static int CheckXetParameters(
2797                 SqlDbType   dbType, 
2798                 long        maxLength, 
2799                 long        actualLength, 
2800                 long        fieldOffset, 
2801                 int         bufferLength, 
2802                 int         bufferOffset, 
2803                 int         length ) {
2804             if ( 0 > fieldOffset )
2805                 throw ADP.NegativeParameter("fieldOffset");
2806
2807             // if negative buffer index, throw
2808             if ( bufferOffset < 0 ) {
2809                 throw ADP.InvalidDestinationBufferIndex( bufferLength, bufferOffset, "bufferOffset" );
2810             }
2811
2812             // skip further length checks for LOB buffer lengths
2813             if(bufferLength < 0){
2814                 length = checked((int) PositiveMin(length, PositiveMin(maxLength, actualLength)));
2815                 if (length < NoLengthLimit) {
2816                     length = NoLengthLimit;
2817                 }
2818                 return length;
2819             }
2820
2821             // if bad buffer index, throw
2822             if ( bufferOffset > bufferLength ) {
2823                 throw ADP.InvalidDestinationBufferIndex( bufferLength, bufferOffset, "bufferOffset" );
2824             }
2825
2826             // if there is not enough room in the buffer for data
2827             if ( checked( length + bufferOffset ) > bufferLength )
2828                 throw ADP.InvalidBufferSizeOrIndex( length, bufferOffset );
2829
2830             if ( length < 0 )
2831                 throw ADP.InvalidDataLength( length );
2832
2833             if ( 0 <= actualLength && actualLength <= fieldOffset ) {
2834                 return 0;
2835             }
2836             
2837             // trim length against both bufferLength and actual or max length
2838             //  (actual or max < 0 means don't trim against that value)
2839             //  Note that parameter UDTs don't know the correct maxlength, so the back end does
2840             //      the trimming.  Actual length should still be trimmed against here, though.
2841             length = Math.Min( length, bufferLength - bufferOffset );
2842
2843             // special case for variants, since their maxLength is actually a bit bigger than
2844             // the actual data length allowed.
2845             if (SqlDbType.Variant == dbType) {
2846                 length = Math.Min( length, TdsEnums.TYPE_SIZE_LIMIT );
2847             }
2848
2849             Debug.Assert( 0 > maxLength || 0 > actualLength || 
2850                     maxLength >= actualLength, "Actual = " + actualLength + ", max = " + maxLength + ", sqldbtype=" + dbType );
2851
2852             if ( 0 <= actualLength ) {
2853                 // Length is guaranteed to be >= 0 coming in and actualLength >= fieldOffset, so this operation guarantees result >= 0
2854                 length = (int) Math.Min((long)length, actualLength - fieldOffset);
2855                 Debug.Assert(length >= 0, "result < 0, actualLength/fieldOffset problem?");
2856             }
2857             else if ( SqlDbType.Udt != dbType && 0 <= maxLength ) {
2858                 length = (int) Math.Min((long)length, maxLength - fieldOffset);
2859                 Debug.Assert(length >= 0, "Result < 0, maxlen/fieldoffset problem?");
2860             }
2861
2862             if ( length < 0 ) {
2863                 return 0;
2864             }
2865             else {
2866                 return length;
2867             }
2868         }
2869
2870         //
2871         // These tables are formal encoding of the "unchecked" method access rules for various types
2872         //  The tables should only be accessed from the CanAccessXetterDirectly methods.
2873         //
2874
2875         // A couple of private constants to increase the getter/setter access tables' constrast
2876         private const bool X = true;
2877         private const bool _ = false;
2878
2879         private static bool[,] __canAccessGetterDirectly = {
2880             // SqlDbTypes as columns (abreviated, but in order)
2881             //  ExtendedClrTypeCodes as rows
2882
2883     //     BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO
2884 /*Bool*/ { _ ,  _ ,  X , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Bool*/
2885 /*Byte*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , X , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Byte*/
2886 /*Char*/ { _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Char*/
2887 /*DTime*/{ _ ,  _ ,  _ , _ , X , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , X  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  X  , _  , X  , _ , },/*DateTime*/
2888 /*DBNul*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*DBNull*/
2889 /*Decim*/{ _ ,  _ ,  _ , _ , _ , X  , _ , _ , _  , X  , _  , _  , _  , _ , _ , _  , _ , X  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Decimal*/
2890 /*Doubl*/{ _ ,  _ ,  _ , _ , _ , _  , X , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Double*/
2891 /*Empty*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Empty*/
2892 /*Int16*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , X , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Int16*/
2893 /*Int32*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , X  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Int32*/
2894 /*Int64*/{ X ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Int64*/
2895 /*SByte*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SByte*/
2896 /*Singl*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , X , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Single*/
2897 /*Strng*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*String*/
2898 /*UIn16*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*UInt16*/
2899 /*UIn32*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*UInt32*/
2900 /*UIn64*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*UInt64*/
2901 /*Objct*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*Object*/
2902 /*BytAr*/{ _ ,  X ,  _ , X , _ , _  , _ , X , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , X , _ , X  , X  , _  , _ , X  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*ByteArray*/
2903 /*ChrAr*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*CharArray*/
2904 /*Guid*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , X , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Guid*/
2905 /*SBin*/ { _ ,  X ,  _ , _ , _ , _  , _ , X , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , X , _ , X  , _  , _  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*SqlBinary*/
2906 /*SBool*/{ _ ,  _ ,  X , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlBoolean*/
2907 /*SByte*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , X , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlByte*/
2908 /*SDTme*/{ _ ,  _ ,  _ , _ , X , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , X  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  X  , _  , X  , _ , },/*SqlDateTime*/
2909 /*SDubl*/{ _ ,  _ ,  _ , _ , _ , _  , X , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlDouble*/
2910 /*SGuid*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , X , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlGuid*/
2911 /*SIn16*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , X , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlInt16*/
2912 /*SIn32*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , X  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlInt32*/
2913 /*SIn64*/{ X ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlInt64*/
2914 /*SMony*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , X  , _  , _  , _  , _ , _ , _  , _ , X  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlMoney*/
2915 /*SDeci*/{ _ ,  _ ,  _ , _ , _ , X  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlDecimal*/
2916 /*SSngl*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , X , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlSingle*/
2917 /*SStrn*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlString*/
2918 /*SChrs*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlChars*/
2919 /*SByts*/{ _ ,  X ,  _ , _ , _ , _  , _ , X , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , X , _ , X  , _  , _  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*SqlBytes*/
2920 /*SXml*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , X  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlXml*/
2921 /*DTbl*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , X,  _  , _  , _  , _ , },/*DataTable*/
2922 /*Rdr */ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , X,  _  , _  , _  , _ , },/*DbDataReader*/
2923 /*EnSDR*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , X,  _  , _  , _  , _ , },/*IEnurerable<SqlDataRecord>*/
2924 /*TmSpn*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , X  , _  , _ , },/*TimeSpan*/
2925 /*DTOst*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , X , },/*DateTimeOffset*/
2926 /*Strm */{ _ ,  X ,  _ , _ , _ , _  , _ , X , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , X  , _  , _  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*Stream*/ 
2927 /*TxRdr*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*TextReader*/
2928 /*XmlRd*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*XmlReader*/
2929     //     BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO
2930         };
2931
2932         private static bool[,] __canAccessSetterDirectly = {
2933         // Setters as columns (labels are abreviated from ExtendedClrTypeCode names)
2934         // SqlDbTypes as rows
2935     //     BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO
2936 /*Bool*/ { _ ,  _ ,  X , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Bool*/
2937 /*Byte*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , X , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Byte*/
2938 /*Char*/ { _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Char*/
2939 /*DTime*/{ _ ,  _ ,  _ , _ , X , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , X  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  X  , _  , X  , _ , },/*DateTime*/
2940 /*DBNul*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*DBNull*/
2941 /*Decim*/{ _ ,  _ ,  _ , _ , _ , X  , _ , _ , _  , X  , _  , _  , _  , _ , _ , _  , _ , X  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Decimal*/
2942 /*Doubl*/{ _ ,  _ ,  _ , _ , _ , _  , X , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Double*/
2943 /*Empty*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Empty*/
2944 /*Int16*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , X , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Int16*/
2945 /*Int32*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , X  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Int32*/
2946 /*Int64*/{ X ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Int64*/
2947 /*SByte*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SByte*/
2948 /*Singl*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , X , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Single*/
2949 /*Strng*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , X  , _ , X  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*String*/
2950 /*UIn16*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*UInt16*/
2951 /*UIn32*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*UInt32*/
2952 /*UIn64*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*UInt64*/
2953 /*Objct*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*Object*/
2954 /*BytAr*/{ _ ,  X ,  _ , _ , _ , _  , _ , X , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , X , _ , X  , _  , X  , _ , X  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*ByteArray*/
2955 /*ChrAr*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*CharArray*/
2956 /*Guid*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , X , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Guid*/
2957 /*SBin*/ { _ ,  X ,  _ , _ , _ , _  , _ , X , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , X , _ , X  , _  , X  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*SqlBinary*/
2958 /*SBool*/{ _ ,  _ ,  X , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlBoolean*/
2959 /*SByte*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , X , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlByte*/
2960 /*SDTme*/{ _ ,  _ ,  _ , _ , X , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , X  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  X  , _  , X  , _ , },/*SqlDateTime*/
2961 /*SDubl*/{ _ ,  _ ,  _ , _ , _ , _  , X , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlDouble*/
2962 /*SGuid*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , X , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlGuid*/
2963 /*SIn16*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , X , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlInt16*/
2964 /*SIn32*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , X  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlInt32*/
2965 /*SIn64*/{ X ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlInt64*/
2966 /*SMony*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , X  , _  , _  , _  , _ , _ , _  , _ , X  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlMoney*/
2967 /*SDeci*/{ _ ,  _ ,  _ , _ , _ , X  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlDecimal*/
2968 /*SSngl*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , X , _ , _  , _ , _  , _  , _ , _ , _  , _  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlSingle*/
2969 /*SStrn*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , X  , _ , X  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlString*/
2970 /*SChrs*/{ _ ,  _ ,  _ , X , _ , _  , _ , _ , _  , _  , X  , X  , X  , _ , _ , _  , _ , _  , X  , _ , _ , _  , X  , X  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlChars*/
2971 /*SByts*/{ _ ,  X ,  _ , _ , _ , _  , _ , X , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , X , _ , X  , _  , X  , _ , _  , _ , _ , _ ,  X , _,  _  , _  , _  , _ , },/*SqlBytes*/
2972 /*SXml*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , X  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*SqlXml*/
2973 /*DTbl*/ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , X,  _  , _  , _  , _ , },/*DataTable*/
2974 /*Rdr */ { _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , X,  _  , _  , _  , _ , },/*DbDataReader*/
2975 /*EnSDR*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , X,  _  , _  , _  , _ , },/*IEnurerable<SqlDataRecord>*/
2976 /*TmSpn*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , X  , _  , _ , },/*TimeSpan*/
2977 /*DTOst*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , X , },/*DateTimeOffset*/
2978 /*Strm */{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*Stream*/ 
2979 /*TxRdr*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*TextReader*/
2980 /*XmlRd*/{ _ ,  _ ,  _ , _ , _ , _  , _ , _ , _  , _  , _  , _  , _  , _ , _ , _  , _ , _  , _  , _ , _ , _  , _  , _  , _ , _  , _ , _ , _ ,  _ , _,  _  , _  , _  , _ , },/*XmlReader*/
2981     //     BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO
2982         };
2983
2984
2985     //
2986     //  Private implementation of common mappings from a given type to corresponding Smi Getter/Setter
2987     //      These classes do type validation, parameter limit validation, nor coercions
2988     //
2989         private static bool IsDBNull_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
2990             bool result = getters.IsDBNull( sink, ordinal );
2991             sink.ProcessMessagesAndThrow();
2992             return result;
2993         }
2994
2995         private static bool GetBoolean_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
2996             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
2997
2998             bool result = getters.GetBoolean( sink, ordinal );
2999             sink.ProcessMessagesAndThrow();
3000             return result;
3001         }
3002
3003         private static byte GetByte_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3004             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3005
3006             byte result = getters.GetByte( sink, ordinal );
3007             sink.ProcessMessagesAndThrow();
3008             return result;
3009         }
3010
3011         private static byte[] GetByteArray_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3012             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3013
3014             long length = getters.GetBytesLength( sink, ordinal );
3015             sink.ProcessMessagesAndThrow();
3016             int len = checked( (int)length );
3017
3018             byte[] buffer = new byte[len];
3019             getters.GetBytes( sink, ordinal, 0, buffer, 0, len );
3020             sink.ProcessMessagesAndThrow();
3021             return buffer;
3022         }
3023
3024         internal static int GetBytes_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length ) {
3025             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3026             Debug.Assert(ordinal >= 0, string.Format("Invalid ordinal: {0}", ordinal));
3027             Debug.Assert(sink != null, "Null SmiEventSink");
3028             Debug.Assert(getters != null, "Null getters");
3029             Debug.Assert(fieldOffset >= 0, string.Format("Invalid field offset: {0}", fieldOffset));
3030             Debug.Assert(buffer != null, "Null buffer");
3031             Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, string.Format("Bad offset or length. bufferOffset: {0}, length: {1}, buffer.Length{2}", bufferOffset, length, buffer.Length));
3032
3033             int result = getters.GetBytes( sink, ordinal, fieldOffset, buffer, bufferOffset, length );
3034             sink.ProcessMessagesAndThrow();
3035             return result;
3036         }
3037
3038         private static long GetBytesLength_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3039             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3040
3041             long result = getters.GetBytesLength( sink, ordinal );
3042             sink.ProcessMessagesAndThrow();
3043             return result;
3044         }
3045
3046
3047         private static char[] GetCharArray_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3048             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3049
3050             long length = getters.GetCharsLength( sink, ordinal );
3051             sink.ProcessMessagesAndThrow();
3052             int len = checked( (int)length );
3053
3054             char[] buffer = new char[len];
3055             getters.GetChars( sink, ordinal, 0, buffer, 0, len );
3056             sink.ProcessMessagesAndThrow();
3057             return buffer;
3058         }
3059
3060         internal static int GetChars_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length ) {
3061             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3062             Debug.Assert(ordinal >= 0, string.Format("Invalid ordinal: {0}", ordinal));
3063             Debug.Assert(sink != null, "Null SmiEventSink");
3064             Debug.Assert(getters != null, "Null getters");
3065             Debug.Assert(fieldOffset >= 0, string.Format("Invalid field offset: {0}", fieldOffset));
3066             Debug.Assert(buffer != null, "Null buffer");
3067             Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, string.Format("Bad offset or length. bufferOffset: {0}, length: {1}, buffer.Length{2}", bufferOffset, length, buffer.Length));
3068
3069             int result = getters.GetChars( sink, ordinal, fieldOffset, buffer, bufferOffset, length );
3070             sink.ProcessMessagesAndThrow();
3071             return result;
3072         }
3073
3074         private static long GetCharsLength_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3075             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3076
3077             long result = getters.GetCharsLength( sink, ordinal );
3078             sink.ProcessMessagesAndThrow();
3079             return result;
3080         }
3081
3082         private static DateTime GetDateTime_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3083             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3084
3085             DateTime result = getters.GetDateTime( sink, ordinal );
3086             sink.ProcessMessagesAndThrow();
3087             return result;
3088         }
3089
3090         private static DateTimeOffset GetDateTimeOffset_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal) {
3091             Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal));
3092
3093             DateTimeOffset result = getters.GetDateTimeOffset(sink, ordinal);
3094             sink.ProcessMessagesAndThrow();
3095             return result;
3096         }
3097
3098         private static Double GetDouble_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3099             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3100
3101             Double result = getters.GetDouble( sink, ordinal );
3102             sink.ProcessMessagesAndThrow();
3103             return result;
3104         }
3105
3106         private static Guid GetGuid_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3107             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3108
3109             Guid result = getters.GetGuid( sink, ordinal );
3110             sink.ProcessMessagesAndThrow();
3111             return result;
3112         }
3113
3114         private static Int16 GetInt16_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3115             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3116
3117             Int16 result = getters.GetInt16( sink, ordinal );
3118             sink.ProcessMessagesAndThrow();
3119             return result;
3120         }
3121
3122         private static Int32 GetInt32_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3123             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3124
3125             Int32 result = getters.GetInt32( sink, ordinal );
3126             sink.ProcessMessagesAndThrow();
3127             return result;
3128         }
3129
3130         private static Int64 GetInt64_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3131             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3132
3133             Int64 result = getters.GetInt64( sink, ordinal );
3134             sink.ProcessMessagesAndThrow();
3135             return result;
3136         }
3137
3138         private static Single GetSingle_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3139             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3140
3141             Single result = getters.GetSingle( sink, ordinal );
3142             sink.ProcessMessagesAndThrow();
3143             return result;
3144         }
3145
3146         private static SqlBinary GetSqlBinary_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3147             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3148
3149             byte[] buffer = GetByteArray_Unchecked( sink, getters, ordinal );
3150             return new SqlBinary( buffer );
3151         }
3152
3153         private static SqlDecimal GetSqlDecimal_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3154             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3155
3156             SqlDecimal result = getters.GetSqlDecimal( sink, ordinal );
3157             sink.ProcessMessagesAndThrow();
3158             return result;
3159         }
3160
3161         private static SqlMoney GetSqlMoney_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3162             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3163
3164             Int64 temp = getters.GetInt64( sink, ordinal );
3165             sink.ProcessMessagesAndThrow();
3166             return new SqlMoney( temp, 1 /* ignored */ );
3167         }
3168
3169         private static SqlXml GetSqlXml_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiContext context ) {
3170             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3171
3172             // allow context to be null so strongly-typed getters can use
3173             //  this method without having to pass along the almost-never-used context as a parameter
3174             //  Looking the context up like this will be slightly slower, but still correct behavior
3175             //  since it's only used to get a scratch stream.
3176             if (null == context && InOutOfProcHelper.InProc) {
3177                 context = SmiContextFactory.Instance.GetCurrentContext();    // In the future we need to push the context checking to a higher level
3178             }
3179
3180             // Note: must make a copy of getter stream, since it will be used beyond
3181             //  this method (valid lifetime of getters is limited).
3182             Stream s = new SmiGettersStream( sink, getters, ordinal, SmiMetaData.DefaultXml );
3183             Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream( s, sink, context );
3184             SqlXml result = new SqlXml( copy );
3185             return result;
3186         }
3187
3188         private static String GetString_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
3189             Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
3190
3191             // Note: depending on different getters, the result string maybed truncated, e.g. for 
3192             // Inproc process, the getter is InProcRecordBuffer (implemented in SqlAcess), string will be
3193             // truncated to 4000 (if length is more than 4000). If MemoryRecordBuffer getter is used, data 
3194             // is not truncated. Please refer VSDD 479655 for more detailed information regarding the string length.
3195             String result = getters.GetString( sink, ordinal );
3196             sink.ProcessMessagesAndThrow();
3197             return result;
3198         }
3199
3200         private static TimeSpan GetTimeSpan_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal) {
3201             Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal));
3202
3203             TimeSpan result = getters.GetTimeSpan(sink, ordinal);
3204             sink.ProcessMessagesAndThrow();
3205             return result;
3206         }
3207
3208         private static void SetBoolean_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Boolean value ) {
3209             setters.SetBoolean( sink, ordinal, value ); 
3210             sink.ProcessMessagesAndThrow();
3211         }
3212
3213         private static void SetByteArray_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, byte[] buffer, int bufferOffset, int length ) {
3214             if ( length > 0 ) {
3215                 setters.SetBytes( sink, ordinal, 0, buffer, bufferOffset, length );
3216                 sink.ProcessMessagesAndThrow();
3217             }
3218             setters.SetBytesLength( sink, ordinal, length );
3219             sink.ProcessMessagesAndThrow();
3220         }
3221
3222         private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metadata, StreamDataFeed feed) {
3223             long len = metadata.MaxLength;
3224             byte[] buff = new byte[constBinBufferSize];
3225             int nWritten = 0;
3226             do {
3227                 int nRead = 0;
3228                 int readSize = constBinBufferSize;
3229                 if (len > 0 && nWritten + readSize > len) {
3230                     readSize = (int)(len - nWritten);
3231                 }
3232
3233                 Debug.Assert(readSize >= 0);
3234
3235                 nRead = feed._source.Read(buff, 0, readSize);
3236
3237                 if (nRead == 0) {
3238                     break;
3239                 }
3240
3241                 setters.SetBytes(sink, ordinal, nWritten, buff, 0, nRead);
3242                 sink.ProcessMessagesAndThrow();
3243
3244                 nWritten += nRead;
3245             } while (len <= 0 || nWritten < len);
3246
3247             setters.SetBytesLength(sink, ordinal, nWritten);
3248             sink.ProcessMessagesAndThrow();
3249         }
3250
3251         private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metadata, TextDataFeed feed) {
3252             long len = metadata.MaxLength;
3253             char[] buff = new char[constTextBufferSize];
3254             int nWritten = 0;
3255             do {
3256                 int nRead = 0;
3257                 int readSize = constTextBufferSize;
3258                 if (len > 0 && nWritten + readSize > len) {
3259                     readSize = (int)(len - nWritten);
3260                 }
3261
3262                 Debug.Assert(readSize >= 0);
3263
3264                 nRead = feed._source.Read(buff, 0, readSize);
3265
3266                 if (nRead == 0) {
3267                     break;
3268                 }
3269
3270                 setters.SetChars(sink, ordinal, nWritten, buff, 0, nRead);
3271                 sink.ProcessMessagesAndThrow();
3272
3273                 nWritten += nRead;
3274             } while (len <= 0 || nWritten < len);
3275
3276             setters.SetCharsLength(sink, ordinal, nWritten);
3277             sink.ProcessMessagesAndThrow();
3278         }
3279
3280         private static void SetByte_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Byte value ) {
3281             setters.SetByte( sink, ordinal, value ); 
3282             sink.ProcessMessagesAndThrow();
3283         }
3284
3285         private static int SetBytes_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length ) {
3286             int result = setters.SetBytes( sink, ordinal, fieldOffset, buffer, bufferOffset, length );
3287             sink.ProcessMessagesAndThrow();
3288             return result;
3289         }
3290
3291         private static void SetCharArray_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, char[] buffer, int bufferOffset, int length ) {
3292             if ( length > 0 ) {
3293                 setters.SetChars( sink, ordinal, 0, buffer, bufferOffset, length );
3294                 sink.ProcessMessagesAndThrow();
3295             }
3296             setters.SetCharsLength( sink, ordinal, length );
3297             sink.ProcessMessagesAndThrow();
3298         }
3299
3300         private static int SetChars_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length ) {
3301             int result = setters.SetChars( sink, ordinal, fieldOffset, buffer, bufferOffset, length );
3302             sink.ProcessMessagesAndThrow();
3303             return result;
3304         }
3305
3306         private static void SetDBNull_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal ) {
3307             setters.SetDBNull( sink, ordinal );
3308             sink.ProcessMessagesAndThrow();
3309         }
3310
3311         private static void SetDecimal_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Decimal value ) {
3312             setters.SetSqlDecimal( sink, ordinal, new SqlDecimal( value ) ); 
3313             sink.ProcessMessagesAndThrow();
3314         }
3315
3316         private static void SetDateTime_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, DateTime value ) {
3317             setters.SetDateTime( sink, ordinal, value ); 
3318             sink.ProcessMessagesAndThrow();
3319         }
3320
3321         private static void SetDateTime2_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value)
3322         {
3323             Debug.Assert(SqlDbType.Variant == metaData.SqlDbType, "Invalid type. This should be called only when the type is variant.");
3324             setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultDateTime2);
3325             setters.SetDateTime(sink, ordinal, value);
3326             sink.ProcessMessagesAndThrow();
3327         }
3328
3329         private static void SetDate_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value)
3330         {
3331             Debug.Assert(SqlDbType.Variant == metaData.SqlDbType, "Invalid type. This should be called only when the type is variant.");
3332             setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultDate);
3333             setters.SetDateTime(sink, ordinal, value);
3334             sink.ProcessMessagesAndThrow();
3335         }
3336
3337         private static void SetTimeSpan_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, TimeSpan value) {
3338             setters.SetTimeSpan(sink, ordinal, value);
3339             sink.ProcessMessagesAndThrow();
3340         }
3341
3342         private static void SetDateTimeOffset_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, DateTimeOffset value) {
3343             setters.SetDateTimeOffset(sink, ordinal, value);
3344             sink.ProcessMessagesAndThrow();
3345         }
3346
3347         private static void SetDouble_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Double value ) {
3348             setters.SetDouble( sink, ordinal, value ); 
3349             sink.ProcessMessagesAndThrow();
3350         }
3351
3352         private static void SetGuid_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Guid value ) {
3353             setters.SetGuid( sink, ordinal, value ); 
3354             sink.ProcessMessagesAndThrow();
3355         }
3356
3357         private static void SetInt16_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Int16 value ) {
3358             setters.SetInt16( sink, ordinal, value ); 
3359             sink.ProcessMessagesAndThrow();
3360         }
3361
3362         private static void SetInt32_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Int32 value ) {
3363             setters.SetInt32( sink, ordinal, value ); 
3364             sink.ProcessMessagesAndThrow();
3365         }
3366
3367         private static void SetInt64_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Int64 value ) {
3368             setters.SetInt64( sink, ordinal, value ); 
3369             sink.ProcessMessagesAndThrow();
3370         }
3371
3372         private static void SetSingle_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Single value ) {
3373             setters.SetSingle( sink, ordinal, value ); 
3374             sink.ProcessMessagesAndThrow();
3375         }
3376
3377         private static void SetSqlBinary_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBinary value, int offset, int length ) {
3378             if ( value.IsNull ) {
3379                 setters.SetDBNull( sink, ordinal );
3380             }
3381             else {
3382                 SetByteArray_Unchecked( sink, setters, ordinal, value.Value, offset, length );
3383             }
3384             sink.ProcessMessagesAndThrow();
3385         }
3386
3387         private static void SetSqlBoolean_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBoolean value ) {
3388             if ( value.IsNull ) {
3389                 setters.SetDBNull( sink, ordinal );
3390             }
3391             else {
3392                 setters.SetBoolean( sink, ordinal, value.Value ); 
3393             }
3394             sink.ProcessMessagesAndThrow();
3395         }
3396
3397         private static void SetSqlByte_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlByte value ) {
3398             if ( value.IsNull ) {
3399                 setters.SetDBNull( sink, ordinal );
3400             }
3401             else {
3402                 setters.SetByte( sink, ordinal, value.Value ); 
3403             }
3404             sink.ProcessMessagesAndThrow();
3405         }
3406
3407         // note: length < 0 indicates write everything
3408         private static void SetSqlBytes_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBytes value, int offset, long length ) {
3409             if ( value.IsNull ) {
3410                 setters.SetDBNull( sink, ordinal );
3411                 sink.ProcessMessagesAndThrow();
3412             }
3413             else {
3414                 int chunkSize;
3415                 if ( length > __maxByteChunkSize || length < 0 ) {
3416                     chunkSize = __maxByteChunkSize;
3417                 }
3418                 else {
3419                     chunkSize = checked( (int)length );
3420                 }
3421
3422                 byte[] buffer = new byte[ chunkSize ];
3423                 long bytesRead;
3424                 long bytesWritten = 1;  // prime value to get into write loop
3425                 long currentOffset = offset;
3426                 long lengthWritten = 0;
3427
3428                 while ( (length < 0  || lengthWritten < length) &&
3429                         0 != ( bytesRead = value.Read( currentOffset, buffer, 0, chunkSize ) ) &&
3430                         0 != bytesWritten ) {
3431                     bytesWritten = setters.SetBytes( sink, ordinal, currentOffset, buffer, 0, checked( (int) bytesRead ) );
3432                     sink.ProcessMessagesAndThrow();
3433                     checked{ currentOffset += bytesWritten; }
3434                     checked{ lengthWritten += bytesWritten; }
3435                 }
3436
3437                 // Make sure to trim any left-over data
3438                 setters.SetBytesLength( sink, ordinal, currentOffset );
3439                 sink.ProcessMessagesAndThrow();
3440             }
3441         }
3442
3443         private static void SetSqlChars_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlChars value, int offset, int length ) {
3444             if ( value.IsNull ) {
3445                 setters.SetDBNull( sink, ordinal );
3446                 sink.ProcessMessagesAndThrow();
3447             }
3448             else {
3449                 int chunkSize;
3450                 if ( length > __maxCharChunkSize || length < 0 ) {
3451                     chunkSize = __maxCharChunkSize;
3452                 }
3453                 else {
3454                     chunkSize = checked( (int)length );
3455                 }
3456
3457                 char[] buffer = new char[ chunkSize ];
3458                 long charsRead;
3459                 long charsWritten = 1;  // prime value to get into write loop
3460                 long currentOffset = offset;
3461                 long lengthWritten = 0;
3462
3463                 while ( (length < 0  || lengthWritten < length) &&
3464                         0 != ( charsRead = value.Read( currentOffset, buffer, 0, chunkSize ) ) &&
3465                         0 != charsWritten ) {
3466                     charsWritten = setters.SetChars( sink, ordinal, currentOffset, buffer, 0, checked( (int) charsRead ) );
3467                     sink.ProcessMessagesAndThrow();
3468                     checked{ currentOffset += charsWritten; }
3469                     checked{ lengthWritten += charsWritten;}
3470                 }
3471
3472                 // Make sure to trim any left-over data
3473                 setters.SetCharsLength( sink, ordinal, currentOffset );
3474                 sink.ProcessMessagesAndThrow();
3475             }
3476         }
3477
3478         private static void SetSqlDateTime_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDateTime value ) {
3479             if ( value.IsNull ) {
3480                 setters.SetDBNull( sink, ordinal );
3481             }
3482             else {
3483                 setters.SetDateTime( sink, ordinal, value.Value ); 
3484             }
3485             sink.ProcessMessagesAndThrow();
3486         }
3487
3488         private static void SetSqlDecimal_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDecimal value ) {
3489             if ( value.IsNull ) {
3490                 setters.SetDBNull( sink, ordinal );
3491             }
3492             else {
3493                 setters.SetSqlDecimal( sink, ordinal, value ); 
3494             }
3495             sink.ProcessMessagesAndThrow();
3496         }
3497
3498         private static void SetSqlDouble_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDouble value ) {
3499             if ( value.IsNull ) {
3500                 setters.SetDBNull( sink, ordinal );
3501             }
3502             else {
3503                 setters.SetDouble( sink, ordinal, value.Value ); 
3504             }
3505             sink.ProcessMessagesAndThrow();
3506         }
3507
3508         private static void SetSqlGuid_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlGuid value ) {
3509             if ( value.IsNull ) {
3510                 setters.SetDBNull( sink, ordinal );
3511             }
3512             else {
3513                 setters.SetGuid( sink, ordinal, value.Value ); 
3514             }
3515             sink.ProcessMessagesAndThrow();
3516         }
3517
3518         private static void SetSqlInt16_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt16 value ) {
3519             if ( value.IsNull ) {
3520                 setters.SetDBNull( sink, ordinal );
3521             }
3522             else {
3523                 setters.SetInt16( sink, ordinal, value.Value ); 
3524             }
3525             sink.ProcessMessagesAndThrow();
3526         }
3527
3528         private static void SetSqlInt32_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt32 value ) {
3529             if ( value.IsNull ) {
3530                 setters.SetDBNull( sink, ordinal );
3531             }
3532             else {
3533                 setters.SetInt32( sink, ordinal, value.Value ); 
3534             }
3535             sink.ProcessMessagesAndThrow();
3536         }
3537
3538         private static void SetSqlInt64_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt64 value ) {
3539             if ( value.IsNull ) {
3540                 setters.SetDBNull( sink, ordinal );
3541             }
3542             else {
3543                 setters.SetInt64( sink, ordinal, value.Value ); 
3544             }
3545             sink.ProcessMessagesAndThrow();
3546         }
3547
3548         private static void SetSqlMoney_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value ) {
3549             if ( value.IsNull ) {
3550                 setters.SetDBNull( sink, ordinal );
3551             }
3552             else {
3553                 if ( SqlDbType.Variant == metaData.SqlDbType ) {
3554                     setters.SetVariantMetaData( sink, ordinal, SmiMetaData.DefaultMoney );
3555                     sink.ProcessMessagesAndThrow();
3556                 }
3557
3558                 setters.SetInt64( sink, ordinal, value.ToSqlInternalRepresentation() );
3559              }
3560             sink.ProcessMessagesAndThrow();
3561         }
3562
3563         private static void SetSqlSingle_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlSingle value ) {
3564             if ( value.IsNull ) {
3565                 setters.SetDBNull( sink, ordinal );
3566             }
3567             else {
3568                 setters.SetSingle( sink, ordinal, value.Value ); 
3569             }
3570             sink.ProcessMessagesAndThrow();
3571         }
3572
3573         private static void SetSqlString_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset, int length ) {
3574             if ( value.IsNull ) {
3575                 setters.SetDBNull( sink, ordinal );
3576                 sink.ProcessMessagesAndThrow();
3577             }
3578             else {
3579                 if (SqlDbType.Variant == metaData.SqlDbType) {
3580                     // Set up a NVarChar metadata with correct LCID/Collation
3581                     metaData = new SmiMetaData(
3582                             SqlDbType.NVarChar, 
3583                             SmiMetaData.MaxUnicodeCharacters,
3584                             0, 
3585                             0, 
3586                             value.LCID,
3587                             value.SqlCompareOptions,
3588                             null);
3589                     setters.SetVariantMetaData( sink, ordinal, metaData );
3590                     sink.ProcessMessagesAndThrow();
3591                 }
3592                 SetString_Unchecked( sink, setters, ordinal, value.Value, offset, length );
3593             }
3594         }
3595
3596         private static void SetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlXml value) {
3597             if (value.IsNull) {
3598                 setters.SetDBNull(sink, ordinal);
3599                 sink.ProcessMessagesAndThrow();
3600             }
3601             else {
3602                 SetXmlReader_Unchecked(sink, setters, ordinal, value.CreateReader());
3603             }
3604         }
3605
3606         private static void SetXmlReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, XmlReader xmlReader) {
3607             // set up writer
3608             XmlWriterSettings WriterSettings = new XmlWriterSettings();
3609             WriterSettings.CloseOutput = false;         // don't close the memory stream
3610             WriterSettings.ConformanceLevel = ConformanceLevel.Fragment;
3611             WriterSettings.Encoding = System.Text.Encoding.Unicode;
3612             WriterSettings.OmitXmlDeclaration = true;
3613
3614             System.IO.Stream target = new SmiSettersStream(sink, setters, ordinal, SmiMetaData.DefaultXml);
3615
3616             XmlWriter xmlWriter = XmlWriter.Create(target, WriterSettings);
3617
3618             // now spool the data into the writer (WriteNode will call Read())
3619             xmlReader.Read();
3620             while (!xmlReader.EOF) {
3621                 xmlWriter.WriteNode(xmlReader, true);
3622             }
3623             xmlWriter.Flush();
3624             sink.ProcessMessagesAndThrow();
3625         }
3626
3627         private static void SetString_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, String value, int offset, int length ) {
3628             setters.SetString( sink, ordinal, value, offset, length ); 
3629             sink.ProcessMessagesAndThrow();
3630         }
3631
3632         private static void SetDataTable_Unchecked(
3633                 SmiEventSink_Default    sink,
3634                 SmiTypedGetterSetter    setters,
3635                 int                     ordinal,
3636                 SmiMetaData             metaData,
3637                 DataTable               value
3638             ) {
3639             // Get the target gettersetter
3640             setters = setters.GetTypedGetterSetter(sink, ordinal);
3641             sink.ProcessMessagesAndThrow();
3642
3643             // iterate over all records
3644             //  if first record was obtained earlier, use it prior to pulling more
3645             ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count];
3646             for(int i=0; i<metaData.FieldMetaData.Count; i++) {
3647                 cellTypes[i] = ExtendedClrTypeCode.Invalid;
3648             }
3649             foreach(DataRow row in value.Rows) {
3650                 setters.NewElement(sink);
3651                 sink.ProcessMessagesAndThrow();
3652
3653                 // Set all columns in the record
3654                 for(int i=0; i<metaData.FieldMetaData.Count; i++) {
3655                     SmiMetaData fieldMetaData = metaData.FieldMetaData[i];
3656                     if (row.IsNull(i)) {
3657                         SetDBNull_Unchecked(sink, setters, i);
3658                     }
3659                     else {
3660                         object cellValue = row[i];
3661
3662                         // Only determine cell types for first row, to save expensive 
3663                         if (ExtendedClrTypeCode.Invalid == cellTypes[i]) {
3664                             cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(
3665                                     fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type, 
3666                                     // 
3667
3668                                     SmiContextFactory.KatmaiVersion 
3669                                     );
3670                         }
3671                         SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null);
3672                     }
3673                 }
3674             }
3675
3676             setters.EndElements(sink);
3677             sink.ProcessMessagesAndThrow();
3678         }
3679
3680         // Set a DbDataReader to a Structured+MultiValued setter (table type)
3681         //  Assumes metaData correctly describes the reader's shape, and consumes only the current resultset
3682         private static void SetDbDataReader_Unchecked(
3683             SmiEventSink_Default    sink,
3684             SmiTypedGetterSetter    setters,
3685             int                     ordinal,
3686             SmiMetaData             metaData,
3687             DbDataReader            value
3688             ) {
3689             // Get the target gettersetter
3690             setters = setters.GetTypedGetterSetter(sink, ordinal);
3691             sink.ProcessMessagesAndThrow();
3692
3693             // Iterate over all rows in the current set of results
3694             while (value.Read()) {
3695                 setters.NewElement(sink);
3696                 sink.ProcessMessagesAndThrow();
3697
3698                 FillCompatibleSettersFromReader(sink, setters, metaData.FieldMetaData, value);
3699             }
3700
3701             setters.EndElements(sink);
3702             sink.ProcessMessagesAndThrow();
3703         }
3704
3705         private static void SetIEnumerableOfSqlDataRecord_Unchecked(
3706             SmiEventSink_Default        sink,
3707             SmiTypedGetterSetter        setters,
3708             int                         ordinal,
3709             SmiMetaData                 metaData,
3710             IEnumerable<SqlDataRecord>  value,
3711             ParameterPeekAheadValue     peekAhead
3712             ) {
3713             // Get target gettersetter
3714             setters = setters.GetTypedGetterSetter(sink, ordinal);
3715             sink.ProcessMessagesAndThrow();
3716
3717             IEnumerator<SqlDataRecord> enumerator = null;
3718             try {
3719                 // Need to copy field metadata to an array to call FillCompatibleITypeSettersFromRecord
3720                 SmiExtendedMetaData[] mdFields = new SmiExtendedMetaData[metaData.FieldMetaData.Count];
3721                 metaData.FieldMetaData.CopyTo(mdFields, 0);
3722
3723                 SmiDefaultFieldsProperty defaults = (SmiDefaultFieldsProperty) metaData.ExtendedProperties[SmiPropertySelector.DefaultFields];
3724
3725                 int recordNumber = 1;   // used only for reporting position when there are errors.
3726
3727                 // obtain enumerator and handle any peekahead values
3728                 if (null != peekAhead && null != peekAhead.FirstRecord) {
3729                     // hook up to enumerator
3730                     enumerator = peekAhead.Enumerator;
3731
3732                     // send the first record that was obtained earlier
3733                     setters.NewElement(sink);
3734                     sink.ProcessMessagesAndThrow();
3735                     FillCompatibleSettersFromRecord(sink, setters, mdFields, peekAhead.FirstRecord, defaults);
3736                     recordNumber++;
3737                 }
3738                 else {
3739                     enumerator = value.GetEnumerator();
3740                 }
3741
3742                 using (enumerator) {
3743                     while(enumerator.MoveNext()) {
3744                         setters.NewElement(sink);
3745                         sink.ProcessMessagesAndThrow();
3746
3747                         SqlDataRecord record = enumerator.Current;
3748
3749                         if (record.FieldCount != mdFields.Length) {
3750                             throw SQL.EnumeratedRecordFieldCountChanged(recordNumber);
3751                         }
3752
3753                         for(int i=0; i<record.FieldCount; i++) {
3754                             if (!MetaDataUtilsSmi.IsCompatible(metaData.FieldMetaData[i], record.GetSqlMetaData(i))) {
3755                                 throw SQL.EnumeratedRecordMetaDataChanged(record.GetName(i), recordNumber);
3756                             }
3757                         }
3758
3759                         FillCompatibleSettersFromRecord(sink, setters, mdFields, record, defaults);
3760                         recordNumber++;
3761                     }
3762
3763                     setters.EndElements(sink);
3764                     sink.ProcessMessagesAndThrow();
3765                 }
3766             }
3767             finally {
3768                 // Clean up!
3769                 IDisposable disposable = enumerator as IDisposable;
3770                 if (null != disposable) {
3771                     disposable.Dispose();
3772                 }
3773             }
3774         }
3775
3776     }
3777 }
3778