@@ -14,7 +14,7 @@ namespace Microsoft.Data.SqlClient.Server
1414 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SqlDataRecord/*' />
1515 public partial class SqlDataRecord : IDataRecord
1616 {
17- private readonly SmiRecordBuffer _recordBuffer ;
17+ private readonly MemoryRecordBuffer _recordBuffer ;
1818 private readonly SmiExtendedMetaData [ ] _columnSmiMetaData ;
1919 private readonly SqlMetaData [ ] _columnMetaData ;
2020 private FieldNameLookup _fieldNameLookup ;
@@ -54,10 +54,22 @@ public virtual string GetDataTypeName(int ordinal)
5454#if NET
5555 [ return : DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicProperties | DynamicallyAccessedMemberTypes . PublicFields ) ]
5656#endif
57- public virtual Type GetFieldType ( int ordinal ) => GetFieldTypeFrameworkSpecific ( ordinal ) ;
57+ public virtual Type GetFieldType ( int ordinal )
58+ {
59+ SqlMetaData md = GetSqlMetaData ( ordinal ) ;
60+
61+ #if NETFRAMEWORK
62+ if ( md . SqlDbType == SqlDbType . Udt )
63+ {
64+ return md . Type ;
65+ }
66+ #endif
67+
68+ return MetaType . GetMetaTypeFromSqlDbType ( md . SqlDbType , isMultiValued : false ) . ClassType ;
69+ }
5870
5971 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetValue/*' />
60- public virtual object GetValue ( int ordinal ) => GetValueFrameworkSpecific ( ordinal ) ;
72+ public virtual object GetValue ( int ordinal ) => ValueUtilsSmi . GetValue200 ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
6173
6274 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetValues/*' />
6375 public virtual int GetValues ( object [ ] values )
@@ -177,7 +189,7 @@ public virtual SqlMetaData GetSqlMetaData(int ordinal)
177189 public virtual Type GetSqlFieldType ( int ordinal ) => MetaType . GetMetaTypeFromSqlDbType ( GetSqlMetaData ( ordinal ) . SqlDbType , false ) . SqlType ;
178190
179191 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlValue/*' />
180- public virtual object GetSqlValue ( int ordinal ) => GetSqlValueFrameworkSpecific ( ordinal ) ;
192+ public virtual object GetSqlValue ( int ordinal ) => ValueUtilsSmi . GetSqlValue200 ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
181193
182194 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlValues/*' />
183195 public virtual int GetSqlValues ( object [ ] values )
@@ -200,10 +212,10 @@ public virtual int GetSqlValues(object[] values)
200212 public virtual SqlBinary GetSqlBinary ( int ordinal ) => ValueUtilsSmi . GetSqlBinary ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
201213
202214 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlBytes/*' />
203- public virtual SqlBytes GetSqlBytes ( int ordinal ) => GetSqlBytesFrameworkSpecific ( ordinal ) ;
215+ public virtual SqlBytes GetSqlBytes ( int ordinal ) => ValueUtilsSmi . GetSqlBytes ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
204216
205217 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlXml/*' />
206- public virtual SqlXml GetSqlXml ( int ordinal ) => GetSqlXmlFrameworkSpecific ( ordinal ) ;
218+ public virtual SqlXml GetSqlXml ( int ordinal ) => ValueUtilsSmi . GetSqlXml ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
207219
208220 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlBoolean/*' />
209221 public virtual SqlBoolean GetSqlBoolean ( int ordinal ) => ValueUtilsSmi . GetSqlBoolean ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
@@ -212,7 +224,7 @@ public virtual int GetSqlValues(object[] values)
212224 public virtual SqlByte GetSqlByte ( int ordinal ) => ValueUtilsSmi . GetSqlByte ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
213225
214226 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlChars/*' />
215- public virtual SqlChars GetSqlChars ( int ordinal ) => GetSqlCharsFrameworkSpecific ( ordinal ) ;
227+ public virtual SqlChars GetSqlChars ( int ordinal ) => ValueUtilsSmi . GetSqlChars ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
216228
217229 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/GetSqlInt16/*' />
218230 public virtual SqlInt16 GetSqlInt16 ( int ordinal ) => ValueUtilsSmi . GetSqlInt16 ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) ) ;
@@ -246,10 +258,78 @@ public virtual int GetSqlValues(object[] values)
246258
247259 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SetValues/*' />
248260 // ISqlUpdateableRecord Implementation
249- public virtual int SetValues ( params object [ ] values ) => SetValuesFrameworkSpecific ( values ) ;
261+ public virtual int SetValues ( params object [ ] values )
262+ {
263+ if ( values == null )
264+ {
265+ throw ADP . ArgumentNull ( nameof ( values ) ) ;
266+ }
267+
268+ // Allow values array longer than FieldCount, just ignore the extra cells.
269+ int copyLength = ( values . Length > FieldCount ) ? FieldCount : values . Length ;
270+
271+ if ( copyLength == 0 )
272+ {
273+ return 0 ;
274+ }
275+
276+ ExtendedClrTypeCode [ ] typeCodes = new ExtendedClrTypeCode [ copyLength ] ;
277+
278+ // Verify all data values as acceptable before changing current state.
279+ for ( int i = 0 ; i < copyLength ; i ++ )
280+ {
281+ SqlMetaData metaData = GetSqlMetaData ( i ) ;
282+ typeCodes [ i ] = MetaDataUtilsSmi . DetermineExtendedTypeCodeForUseWithSqlDbType (
283+ metaData . SqlDbType ,
284+ isMultiValued : false ,
285+ values [ i ] ,
286+ metaData . Type ) ;
287+ if ( typeCodes [ i ] == ExtendedClrTypeCode . Invalid )
288+ {
289+ throw ADP . InvalidCast ( ) ;
290+ }
291+ }
292+
293+ // Now move the data. We've already validated the element types above, so this will
294+ // only throw if an invalid UDT was sent.
295+ for ( int i = 0 ; i < copyLength ; i ++ )
296+ {
297+ ValueUtilsSmi . SetCompatibleValueV200 (
298+ _recordBuffer ,
299+ ordinal : i ,
300+ GetSmiMetaData ( i ) ,
301+ values [ i ] ,
302+ typeCodes [ i ] ,
303+ offset : 0 ,
304+ peekAhead : null ) ;
305+ }
306+
307+ return copyLength ;
308+ }
250309
251310 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SetValue/*' />
252- public virtual void SetValue ( int ordinal , object value ) => SetValueFrameworkSpecific ( ordinal , value ) ;
311+ public virtual void SetValue ( int ordinal , object value )
312+ {
313+ SqlMetaData metaData = GetSqlMetaData ( ordinal ) ;
314+ ExtendedClrTypeCode typeCode = MetaDataUtilsSmi . DetermineExtendedTypeCodeForUseWithSqlDbType (
315+ metaData . SqlDbType ,
316+ isMultiValued : false ,
317+ value ,
318+ metaData . Type ) ;
319+ if ( typeCode == ExtendedClrTypeCode . Invalid )
320+ {
321+ throw ADP . InvalidCast ( ) ;
322+ }
323+
324+ ValueUtilsSmi . SetCompatibleValueV200 (
325+ _recordBuffer ,
326+ ordinal ,
327+ GetSmiMetaData ( ordinal ) ,
328+ value ,
329+ typeCode ,
330+ offset : 0 ,
331+ peekAhead : null ) ;
332+ }
253333
254334 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SetBoolean/*' />
255335 public virtual void SetBoolean ( int ordinal , bool value ) => ValueUtilsSmi . SetBoolean ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) , value ) ;
@@ -290,10 +370,10 @@ public virtual int GetSqlValues(object[] values)
290370 public virtual void SetDateTime ( int ordinal , DateTime value ) => ValueUtilsSmi . SetDateTime ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) , value ) ;
291371
292372 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SetTimeSpan/*' />
293- public virtual void SetTimeSpan ( int ordinal , TimeSpan value ) => SetTimeSpanFrameworkSpecific ( ordinal , value ) ;
373+ public virtual void SetTimeSpan ( int ordinal , TimeSpan value ) => ValueUtilsSmi . SetTimeSpan ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) , value ) ;
294374
295375 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SetDateTimeOffset/*' />
296- public virtual void SetDateTimeOffset ( int ordinal , DateTimeOffset value ) => SetDateTimeOffsetFrameworkSpecific ( ordinal , value ) ;
376+ public virtual void SetDateTimeOffset ( int ordinal , DateTimeOffset value ) => ValueUtilsSmi . SetDateTimeOffset ( _recordBuffer , ordinal , GetSmiMetaData ( ordinal ) , value ) ;
297377
298378 /// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient.Server/SqlDataRecord.xml' path='docs/members[@name="SqlDataRecord"]/SetDBNull/*' />
299379 public virtual void SetDBNull ( int ordinal )
0 commit comments