2 // System.Data.SqlClient.SqlDataReader.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
9 // (C) Ximian, Inc 2002
10 // (C) Daniel Morgan 2002
11 // Copyright (C) Tim Coleman, 2002
15 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using Mono.Data.Tds.Protocol;
41 using System.Collections;
42 using System.ComponentModel;
44 using System.Data.Common;
45 using System.Data.SqlTypes;
47 namespace System.Data.SqlClient
50 public class SqlDataReader : DbDataReader, IDataReader, IDisposable, IDataRecord
52 public sealed class SqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
58 ArrayList dataTypeNames;
64 DataTable schemaTable;
70 int visibleFieldCount;
75 const int COLUMN_NAME_IDX = 0;
76 const int COLUMN_ORDINAL_IDX = 1;
77 const int COLUMN_SIZE_IDX = 2;
78 const int NUMERIC_PRECISION_IDX = 3;
79 const int NUMERIC_SCALE_IDX = 4;
80 const int IS_UNIQUE_IDX = 5;
81 const int IS_KEY_IDX = 6;
82 const int BASE_SERVER_NAME_IDX = 7;
83 const int BASE_CATALOG_NAME_IDX = 8;
84 const int BASE_COLUMN_NAME_IDX = 9;
85 const int BASE_SCHEMA_NAME_IDX = 10;
86 const int BASE_TABLE_NAME_IDX = 11;
87 const int DATA_TYPE_IDX = 12;
88 const int ALLOW_DBNULL_IDX = 13;
89 const int PROVIDER_TYPE_IDX = 14;
90 const int IS_ALIASED_IDX = 15;
91 const int IS_EXPRESSION_IDX = 16;
92 const int IS_IDENTITY_IDX = 17;
93 const int IS_AUTO_INCREMENT_IDX = 18;
94 const int IS_ROW_VERSION_IDX = 19;
95 const int IS_HIDDEN_IDX = 20;
96 const int IS_LONG_IDX = 21;
97 const int IS_READ_ONLY_IDX = 22;
101 internal SqlDataReader (SqlCommand command)
105 readResultUsed = false;
106 this.command = command;
109 command.Tds.RecordsAffected = -1;
111 visibleFieldCount = 0;
116 #endregion // Constructors
133 get { return command.Tds.Columns.Count; }
141 get { return isClosed; }
148 object this [int i] {
149 get { return GetValue (i); }
156 object this [string name] {
157 get { return GetValue (GetOrdinal (name)); }
164 int RecordsAffected {
166 return command.Tds.RecordsAffected;
180 readResult = ReadRecord ();
185 public override int VisibleFieldCount {
186 get { return visibleFieldCount; }
189 protected SqlConnection Connection {
190 get { return command.Connection; }
193 protected bool IsCommandBehavior (CommandBehavior condition) {
194 return condition == command.CommandBehavior;
198 #endregion // Properties
210 // skip to end & read output parameters.
211 while (NextResult ())
214 command.CloseDataReader ();
217 private static DataTable ConstructSchemaTable ()
219 Type booleanType = typeof (bool);
220 Type stringType = typeof (string);
221 Type intType = typeof (int);
222 Type typeType = typeof (Type);
223 Type shortType = typeof (short);
225 DataTable schemaTable = new DataTable ("SchemaTable");
226 schemaTable.Columns.Add ("ColumnName", stringType);
227 schemaTable.Columns.Add ("ColumnOrdinal", intType);
228 schemaTable.Columns.Add ("ColumnSize", intType);
229 schemaTable.Columns.Add ("NumericPrecision", shortType);
230 schemaTable.Columns.Add ("NumericScale", shortType);
231 schemaTable.Columns.Add ("IsUnique", booleanType);
232 schemaTable.Columns.Add ("IsKey", booleanType);
233 schemaTable.Columns.Add ("BaseServerName", stringType);
234 schemaTable.Columns.Add ("BaseCatalogName", stringType);
235 schemaTable.Columns.Add ("BaseColumnName", stringType);
236 schemaTable.Columns.Add ("BaseSchemaName", stringType);
237 schemaTable.Columns.Add ("BaseTableName", stringType);
238 schemaTable.Columns.Add ("DataType", typeType);
239 schemaTable.Columns.Add ("AllowDBNull", booleanType);
240 schemaTable.Columns.Add ("ProviderType", intType);
241 schemaTable.Columns.Add ("IsAliased", booleanType);
242 schemaTable.Columns.Add ("IsExpression", booleanType);
243 schemaTable.Columns.Add ("IsIdentity", booleanType);
244 schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
245 schemaTable.Columns.Add ("IsRowVersion", booleanType);
246 schemaTable.Columns.Add ("IsHidden", booleanType);
247 schemaTable.Columns.Add ("IsLong", booleanType);
248 schemaTable.Columns.Add ("IsReadOnly", booleanType);
253 private void GetSchemaRowTypeName (TdsColumnType ctype, int csize, out string typeName)
259 GetSchemaRowType (ctype, csize, out dbType, out fieldType, out isLong, out typeName);
262 private void GetSchemaRowFieldType (TdsColumnType ctype, int csize, out Type fieldType)
268 GetSchemaRowType (ctype, csize, out dbType, out fieldType, out isLong, out typeName);
271 private void GetSchemaRowDbType (TdsColumnType ctype, int csize, out int dbType)
277 GetSchemaRowType (ctype, csize, out dbType, out fieldType, out isLong, out typeName);
280 private void GetSchemaRowType (TdsColumnType ctype, int csize,
281 out int dbType, out Type fieldType,
282 out bool isLong, out string typeName)
285 typeName = string.Empty;
287 fieldType = typeof (Type);
290 case TdsColumnType.Int1:
291 case TdsColumnType.Int2:
292 case TdsColumnType.Int4:
293 case TdsColumnType.IntN:
296 typeName = "tinyint";
297 dbType = (int) SqlDbType.TinyInt;
298 fieldType = typeof (byte);
302 typeName = "smallint";
303 dbType = (int) SqlDbType.SmallInt;
304 fieldType = typeof (short);
309 dbType = (int) SqlDbType.Int;
310 fieldType = typeof (int);
315 dbType = (int) SqlDbType.BigInt;
316 fieldType = typeof (long);
321 case TdsColumnType.Real:
322 case TdsColumnType.Float8:
323 case TdsColumnType.FloatN:
327 dbType = (int) SqlDbType.Real;
328 fieldType = typeof (float);
333 dbType = (int) SqlDbType.Float;
334 fieldType = typeof (double);
339 case TdsColumnType.Image :
341 dbType = (int) SqlDbType.Image;
342 fieldType = typeof (byte[]);
345 case TdsColumnType.Text :
347 dbType = (int) SqlDbType.Text;
348 fieldType = typeof (string);
351 case TdsColumnType.UniqueIdentifier :
352 typeName = "uniqueidentifier";
353 dbType = (int) SqlDbType.UniqueIdentifier;
354 fieldType = typeof (Guid);
357 case TdsColumnType.VarBinary :
358 case TdsColumnType.BigVarBinary :
359 typeName = "varbinary";
360 dbType = (int) SqlDbType.VarBinary;
361 fieldType = typeof (byte[]);
364 case TdsColumnType.VarChar :
365 case TdsColumnType.BigVarChar :
366 typeName = "varchar";
367 dbType = (int) SqlDbType.VarChar;
368 fieldType = typeof (string);
371 case TdsColumnType.Binary :
372 case TdsColumnType.BigBinary :
374 dbType = (int) SqlDbType.Binary;
375 fieldType = typeof (byte[]);
378 case TdsColumnType.Char :
379 case TdsColumnType.BigChar :
381 dbType = (int) SqlDbType.Char;
382 fieldType = typeof (string);
385 case TdsColumnType.Bit :
386 case TdsColumnType.BitN :
388 dbType = (int) SqlDbType.Bit;
389 fieldType = typeof (bool);
392 case TdsColumnType.DateTime4 :
393 case TdsColumnType.DateTime :
394 case TdsColumnType.DateTimeN :
395 typeName = "datetime";
396 dbType = (int) SqlDbType.DateTime;
397 fieldType = typeof (DateTime);
400 case TdsColumnType.Money :
401 case TdsColumnType.MoneyN :
402 case TdsColumnType.Money4 :
404 dbType = (int) SqlDbType.Money;
405 fieldType = typeof (decimal);
408 case TdsColumnType.NText :
410 dbType = (int) SqlDbType.NText;
411 fieldType = typeof (string);
414 case TdsColumnType.NVarChar :
415 typeName = "nvarchar";
416 dbType = (int) SqlDbType.NVarChar;
417 fieldType = typeof (string);
420 case TdsColumnType.Decimal :
421 case TdsColumnType.Numeric :
422 typeName = "decimal";
423 dbType = (int) SqlDbType.Decimal;
424 fieldType = typeof (decimal);
427 case TdsColumnType.NChar :
429 dbType = (int) SqlDbType.NChar;
430 fieldType = typeof (string);
433 case TdsColumnType.SmallMoney :
434 typeName = "smallmoney";
435 dbType = (int) SqlDbType.SmallMoney;
436 fieldType = typeof (decimal);
440 typeName = "variant";
441 dbType = (int) SqlDbType.Variant;
442 fieldType = typeof (object);
451 void Dispose (bool disposing)
455 if (schemaTable != null)
456 schemaTable.Dispose ();
468 bool GetBoolean (int i)
470 object value = GetValue (i);
471 if (!(value is bool)) {
472 if (value is DBNull) throw new SqlNullValueException ();
473 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
484 object value = GetValue (i);
485 if (!(value is byte)) {
486 if (value is DBNull) throw new SqlNullValueException ();
487 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
496 long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
498 if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
500 long len = ((Tds)command.Tds).GetSequentialColumnValue (i, dataIndex, buffer, bufferIndex, length);
502 throw new InvalidCastException ("Invalid attempt to GetBytes on column "
503 + "'" + command.Tds.Columns[i]["ColumnName"] +
504 "'." + "The GetBytes function"
505 + " can only be used on columns of type Text, NText, or Image");
507 } catch (TdsInternalException ex) {
508 command.Connection.Close ();
509 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
513 object value = GetValue (i);
514 if (!(value is byte [])) {
515 if (value is DBNull) throw new SqlNullValueException ();
516 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
519 if ( buffer == null )
520 return ((byte []) value).Length; // Return length of data
522 // Copy data into buffer
523 int availLen = (int) ( ( (byte []) value).Length - dataIndex);
524 if (availLen < length)
526 Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
527 return length; // return actual read count
530 [EditorBrowsableAttribute (EditorBrowsableState.Never)]
537 object value = GetValue (i);
538 if (!(value is char)) {
539 if (value is DBNull) throw new SqlNullValueException ();
540 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
549 long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
551 if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
552 Encoding encoding = null;
554 TdsColumnType colType = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
556 case TdsColumnType.Text :
557 case TdsColumnType.VarChar:
558 case TdsColumnType.Char:
559 case TdsColumnType.BigVarChar:
560 encoding = Encoding.ASCII;
562 case TdsColumnType.NText :
563 case TdsColumnType.NVarChar:
564 case TdsColumnType.NChar:
565 encoding = Encoding.Unicode;
573 if (buffer == null) {
574 count = GetBytes (i,0,(byte[]) null,0,0);
579 byte[] arr = new byte [length];
580 count = GetBytes (i, dataIndex, arr, 0, length);
582 throw new InvalidCastException ("Specified cast is not valid");
584 Char[] val = encoding.GetChars (arr, 0, (int)count);
585 val.CopyTo (buffer, bufferIndex);
590 object value = GetValue (i);
593 valueBuffer = (char[])value;
594 else if (value is string)
595 valueBuffer = ((string)value).ToCharArray();
597 if (value is DBNull) throw new SqlNullValueException ();
598 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
601 if ( buffer == null ) {
602 // Return length of data
603 return valueBuffer.Length;
606 // Copy data into buffer
607 Array.Copy (valueBuffer, (int) dataIndex, buffer, bufferIndex, length);
608 return valueBuffer.Length - dataIndex;
613 [EditorBrowsableAttribute (EditorBrowsableState.Never)]
614 public new IDataReader GetData (int i)
616 return ((IDataReader) this [i]);
624 string GetDataTypeName (int i)
630 if (i < 0 || i >= command.Tds.Columns.Count)
631 throw new IndexOutOfRangeException ();
633 ctype = (TdsColumnType) command.Tds.Columns[i].ColumnType;
634 csize = (int) command.Tds.Columns[i].ColumnSize;
636 ctype = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
637 csize = (int) command.Tds.Columns[i]["ColumnSize"];
639 GetSchemaRowTypeName (ctype, csize, out datatypeName);
647 DateTime GetDateTime (int i)
649 object value = GetValue (i);
650 if (!(value is DateTime)) {
651 if (value is DBNull) throw new SqlNullValueException ();
652 else throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
654 return (DateTime) value;
661 decimal GetDecimal (int i)
663 object value = GetValue (i);
664 if (!(value is decimal)) {
665 if (value is DBNull) throw new SqlNullValueException ();
666 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
668 return (decimal) value;
675 double GetDouble (int i)
677 object value = GetValue (i);
678 if (!(value is double)) {
679 if (value is DBNull) throw new SqlNullValueException ();
680 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
682 return (double) value;
689 Type GetFieldType (int i)
695 if (i < 0 || i >= command.Tds.Columns.Count)
696 throw new IndexOutOfRangeException ();
698 ctype = (TdsColumnType) command.Tds.Columns[i].ColumnType;
699 csize = (int) command.Tds.Columns[i].ColumnSize;
701 ctype = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
702 csize = (int) command.Tds.Columns[i]["ColumnSize"];
704 GetSchemaRowFieldType (ctype, csize, out fieldType);
712 float GetFloat (int i)
714 object value = GetValue (i);
715 if (!(value is float)) {
716 if (value is DBNull) throw new SqlNullValueException ();
717 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
719 return (float) value;
728 object value = GetValue (i);
729 if (!(value is Guid)) {
730 if (value is DBNull) throw new SqlNullValueException ();
731 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
740 short GetInt16 (int i)
742 object value = GetValue (i);
743 if (!(value is short)) {
744 if (value is DBNull) throw new SqlNullValueException ();
745 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
747 return (short) value;
756 object value = GetValue (i);
757 if (!(value is int)) {
758 if (value is DBNull) throw new SqlNullValueException ();
759 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
768 long GetInt64 (int i)
770 object value = GetValue (i);
771 if (!(value is long)) {
772 if (value is DBNull) throw new SqlNullValueException ();
773 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
782 string GetName (int i)
784 if (i < 0 || i >= command.Tds.Columns.Count)
785 throw new IndexOutOfRangeException ();
787 return (string) command.Tds.Columns[i].ColumnName;
789 return (string) command.Tds.Columns[i]["ColumnName"];
797 int GetOrdinal (string name)
800 foreach (TdsDataColumn schema in command.Tds.Columns) {
802 colName = schema.ColumnName;
803 if (colName.Equals (name) || String.Compare (colName, name, true) == 0)
804 return (int) schema.ColumnOrdinal;
806 colName = (string) schema["ColumnName"];
807 if (colName.Equals (name) || String.Compare (colName, name, true) == 0)
808 return (int) schema["ColumnOrdinal"];
811 throw new IndexOutOfRangeException ();
818 DataTable GetSchemaTable ()
822 if (schemaTable == null)
823 schemaTable = ConstructSchemaTable ();
825 if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
831 dataTypeNames = new ArrayList (command.Tds.Columns.Count);
833 foreach (TdsDataColumn schema in command.Tds.Columns) {
834 DataRow row = schemaTable.NewRow ();
837 row [COLUMN_NAME_IDX] = GetSchemaValue (schema.ColumnName);
838 row [COLUMN_ORDINAL_IDX] = GetSchemaValue (schema.ColumnOrdinal);
839 row [IS_UNIQUE_IDX] = GetSchemaValue (schema.IsUnique);
840 row [IS_AUTO_INCREMENT_IDX] = GetSchemaValue (schema.IsAutoIncrement);
841 row [IS_ROW_VERSION_IDX] = GetSchemaValue (schema.IsRowVersion);
842 row [IS_HIDDEN_IDX] = GetSchemaValue (schema.IsHidden);
843 row [IS_IDENTITY_IDX] = GetSchemaValue (schema.IsIdentity);
844 row [COLUMN_SIZE_IDX] = GetSchemaValue (schema.ColumnSize);
845 row [NUMERIC_PRECISION_IDX] = GetSchemaValue (schema.NumericPrecision);
846 row [NUMERIC_SCALE_IDX] = GetSchemaValue (schema.NumericScale);
847 row [IS_KEY_IDX] = GetSchemaValue (schema.IsKey);
848 row [IS_ALIASED_IDX] = GetSchemaValue (schema.IsAliased);
849 row [IS_EXPRESSION_IDX] = GetSchemaValue (schema.IsExpression);
850 row [IS_READ_ONLY_IDX] = GetSchemaValue (schema.IsReadOnly);
851 row [BASE_SERVER_NAME_IDX] = GetSchemaValue (schema.BaseServerName);
852 row [BASE_CATALOG_NAME_IDX] = GetSchemaValue (schema.BaseCatalogName);
853 row [BASE_COLUMN_NAME_IDX] = GetSchemaValue (schema.BaseColumnName);
854 row [BASE_SCHEMA_NAME_IDX] = GetSchemaValue (schema.BaseSchemaName);
855 row [BASE_TABLE_NAME_IDX] = GetSchemaValue (schema.BaseTableName);
856 row [ALLOW_DBNULL_IDX] = GetSchemaValue (schema.AllowDBNull);
858 row ["ColumnName"] = GetSchemaValue (schema, "ColumnName");
859 row ["ColumnOrdinal"] = GetSchemaValue (schema, "ColumnOrdinal");
860 row ["IsUnique"] = GetSchemaValue (schema, "IsUnique");
861 row ["IsAutoIncrement"] = GetSchemaValue (schema, "IsAutoIncrement");
862 row ["IsRowVersion"] = GetSchemaValue (schema, "IsRowVersion");
863 row ["IsHidden"] = GetSchemaValue (schema, "IsHidden");
864 row ["IsIdentity"] = GetSchemaValue (schema, "IsIdentity");
865 row ["ColumnSize"] = GetSchemaValue (schema, "ColumnSize");
866 row ["NumericPrecision"] = GetSchemaValue (schema, "NumericPrecision");
867 row ["NumericScale"] = GetSchemaValue (schema, "NumericScale");
868 row ["IsKey"] = GetSchemaValue (schema, "IsKey");
869 row ["IsAliased"] = GetSchemaValue (schema, "IsAliased");
870 row ["IsExpression"] = GetSchemaValue (schema, "IsExpression");
871 row ["IsReadOnly"] = GetSchemaValue (schema, "IsReadOnly");
872 row ["BaseServerName"] = GetSchemaValue (schema, "BaseServerName");
873 row ["BaseCatalogName"] = GetSchemaValue (schema, "BaseCatalogName");
874 row ["BaseColumnName"] = GetSchemaValue (schema, "BaseColumnName");
875 row ["BaseSchemaName"] = GetSchemaValue (schema, "BaseSchemaName");
876 row ["BaseTableName"] = GetSchemaValue (schema, "BaseTableName");
877 row ["AllowDBNull"] = GetSchemaValue (schema, "AllowDBNull");
879 // We don't always get the base column name.
880 if (row [BASE_COLUMN_NAME_IDX] == DBNull.Value)
881 row [BASE_COLUMN_NAME_IDX] = row [COLUMN_NAME_IDX];
889 ctype = (TdsColumnType) schema.ColumnType;
890 csize = (int) schema.ColumnSize;
892 ctype = (TdsColumnType) schema ["ColumnType"];
893 csize = (int) schema ["ColumnSize"];
896 GetSchemaRowType (ctype, csize, out dbType,
897 out fieldType, out isLong, out typeName);
899 dataTypeNames.Add (typeName);
900 row [PROVIDER_TYPE_IDX] = dbType;
901 row [DATA_TYPE_IDX] = fieldType;
902 row [IS_LONG_IDX] = isLong;
904 if ((bool)row [IS_HIDDEN_IDX] == false)
905 visibleFieldCount += 1;
908 schemaTable.Rows.Add (row);
913 private static object GetSchemaValue (TdsDataColumn schema, string key)
915 object val = schema [key];
922 static object GetSchemaValue (object value)
934 SqlBinary GetSqlBinary (int i)
936 object value = GetSqlValue (i);
937 if (!(value is SqlBinary))
938 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
939 return (SqlBinary) value;
946 SqlBoolean GetSqlBoolean (int i)
948 object value = GetSqlValue (i);
949 if (!(value is SqlBoolean))
950 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
951 return (SqlBoolean) value;
958 SqlByte GetSqlByte (int i)
960 object value = GetSqlValue (i);
961 if (!(value is SqlByte))
962 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
963 return (SqlByte) value;
970 SqlDateTime GetSqlDateTime (int i)
972 object value = GetSqlValue (i);
973 if (!(value is SqlDateTime))
974 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
975 return (SqlDateTime) value;
982 SqlDecimal GetSqlDecimal (int i)
984 object value = GetSqlValue (i);
985 if (!(value is SqlDecimal))
986 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
987 return (SqlDecimal) value;
994 SqlDouble GetSqlDouble (int i)
996 object value = GetSqlValue (i);
997 if (!(value is SqlDouble))
998 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
999 return (SqlDouble) value;
1006 SqlGuid GetSqlGuid (int i)
1008 object value = GetSqlValue (i);
1009 if (!(value is SqlGuid))
1010 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1011 return (SqlGuid) value;
1018 SqlInt16 GetSqlInt16 (int i)
1020 object value = GetSqlValue (i);
1021 if (!(value is SqlInt16))
1022 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1023 return (SqlInt16) value;
1030 SqlInt32 GetSqlInt32 (int i)
1032 object value = GetSqlValue (i);
1033 if (!(value is SqlInt32))
1034 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1035 return (SqlInt32) value;
1042 SqlInt64 GetSqlInt64 (int i)
1044 object value = GetSqlValue (i);
1045 // TDS 7.0 returns bigint as decimal(19,0)
1046 if (value is SqlDecimal) {
1047 TdsDataColumn schema = command.Tds.Columns[i];
1048 byte precision, scale;
1051 precision = (byte)schema.NumericPrecision;
1052 scale = (byte)schema.NumericScale;
1054 precision = (byte)schema["NumericPrecision"];
1055 scale = (byte)schema["NumericScale"];
1057 if (precision == 19 && scale == 0)
1058 value = (SqlInt64) (SqlDecimal) value;
1060 if (!(value is SqlInt64))
1061 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1062 return (SqlInt64) value;
1069 SqlMoney GetSqlMoney (int i)
1071 object value = GetSqlValue (i);
1072 if (!(value is SqlMoney))
1073 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1074 return (SqlMoney) value;
1081 SqlSingle GetSqlSingle (int i)
1083 object value = GetSqlValue (i);
1084 if (!(value is SqlSingle))
1085 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1086 return (SqlSingle) value;
1093 SqlString GetSqlString (int i)
1095 object value = GetSqlValue (i);
1096 if (!(value is SqlString))
1097 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1098 return (SqlString) value;
1102 public virtual SqlXml GetSqlXml (int i)
1104 object value = GetSqlValue (i);
1105 if (!(value is SqlXml)) {
1106 if (value is DBNull) throw new SqlNullValueException ();
1107 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1109 return (SqlXml) value;
1117 object GetSqlValue (int i)
1120 TdsColumnType ctype;
1122 if (i < 0 || i >= command.Tds.Columns.Count)
1123 throw new IndexOutOfRangeException ();
1125 ctype = (TdsColumnType) command.Tds.Columns[i].ColumnType;
1126 csize = (int) command.Tds.Columns[i].ColumnSize;
1128 ctype = (TdsColumnType) command.Tds.Columns[i]["ColumnType"];
1129 csize = (int) command.Tds.Columns[i]["ColumnSize"];
1131 GetSchemaRowDbType (ctype, csize, out dbType);
1132 SqlDbType type = (SqlDbType) dbType;
1133 object value = GetValue (i);
1136 case SqlDbType.BigInt:
1137 if (value == DBNull.Value)
1138 return SqlInt64.Null;
1139 return (SqlInt64) ((long) value);
1140 case SqlDbType.Binary:
1141 case SqlDbType.Image:
1142 case SqlDbType.VarBinary:
1143 case SqlDbType.Timestamp:
1144 if (value == DBNull.Value)
1145 return SqlBinary.Null;
1146 return (SqlBinary) ((byte[]) value);
1148 if (value == DBNull.Value)
1149 return SqlBoolean.Null;
1150 return (SqlBoolean) ((bool) value);
1151 case SqlDbType.Char:
1152 case SqlDbType.NChar:
1153 case SqlDbType.NText:
1154 case SqlDbType.NVarChar:
1155 case SqlDbType.Text:
1156 case SqlDbType.VarChar:
1157 if (value == DBNull.Value)
1158 return SqlString.Null;
1159 return (SqlString) ((string) value);
1160 case SqlDbType.DateTime:
1161 case SqlDbType.SmallDateTime:
1162 if (value == DBNull.Value)
1163 return SqlDateTime.Null;
1164 return (SqlDateTime) ((DateTime) value);
1165 case SqlDbType.Decimal:
1166 if (value == DBNull.Value)
1167 return SqlDecimal.Null;
1168 if (value is TdsBigDecimal)
1169 return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
1170 return (SqlDecimal) ((decimal) value);
1171 case SqlDbType.Float:
1172 if (value == DBNull.Value)
1173 return SqlDouble.Null;
1174 return (SqlDouble) ((double) value);
1176 if (value == DBNull.Value)
1177 return SqlInt32.Null;
1178 return (SqlInt32) ((int) value);
1179 case SqlDbType.Money:
1180 case SqlDbType.SmallMoney:
1181 if (value == DBNull.Value)
1182 return SqlMoney.Null;
1183 return (SqlMoney) ((decimal) value);
1184 case SqlDbType.Real:
1185 if (value == DBNull.Value)
1186 return SqlSingle.Null;
1187 return (SqlSingle) ((float) value);
1188 case SqlDbType.UniqueIdentifier:
1189 if (value == DBNull.Value)
1190 return SqlGuid.Null;
1191 return (SqlGuid) ((Guid) value);
1192 case SqlDbType.SmallInt:
1193 if (value == DBNull.Value)
1194 return SqlInt16.Null;
1195 return (SqlInt16) ((short) value);
1196 case SqlDbType.TinyInt:
1197 if (value == DBNull.Value)
1198 return SqlByte.Null;
1199 return (SqlByte) ((byte) value);
1202 if (value == DBNull.Value)
1203 return SqlByte.Null;
1204 return (SqlXml) value;
1208 throw new InvalidOperationException ("The type of this column is unknown.");
1215 int GetSqlValues (object[] values)
1218 int columnCount = command.Tds.Columns.Count;
1219 int arrayCount = values.Length;
1221 if (arrayCount > columnCount)
1222 count = columnCount;
1226 for (int i = 0; i < count; i += 1)
1227 values [i] = GetSqlValue (i);
1236 string GetString (int i)
1238 object value = GetValue (i);
1239 if (!(value is string)) {
1240 if (value is DBNull) throw new SqlNullValueException ();
1241 throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1243 return (string) value;
1250 object GetValue (int i)
1252 if (i < 0 || i >= command.Tds.Columns.Count)
1253 throw new IndexOutOfRangeException ();
1256 if ((command.CommandBehavior & CommandBehavior.SequentialAccess) != 0) {
1257 return ((Tds)command.Tds).GetSequentialColumnValue (i);
1259 } catch (TdsInternalException ex) {
1260 command.Connection.Close ();
1261 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
1264 return command.Tds.ColumnValues [i];
1271 int GetValues (object[] values)
1273 int len = values.Length;
1274 int bigDecimalIndex = command.Tds.ColumnValues.BigDecimalIndex;
1276 // If a four-byte decimal is stored, then we can't convert to
1277 // a native type. Throw an OverflowException.
1278 if (bigDecimalIndex >= 0 && bigDecimalIndex < len)
1279 throw new OverflowException ();
1281 command.Tds.ColumnValues.CopyTo (0, values, 0,
1282 len > command.Tds.ColumnValues.Count ? command.Tds.ColumnValues.Count : len);
1283 } catch (TdsInternalException ex) {
1284 command.Connection.Close ();
1285 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
1287 return (len < FieldCount ? len : FieldCount);
1291 void IDisposable.Dispose ()
1294 GC.SuppressFinalize (this);
1299 public override IEnumerator GetEnumerator ()
1301 IEnumerator IEnumerable.GetEnumerator ()
1304 return new DbEnumerator (this);
1311 bool IsDBNull (int i)
1313 return GetValue (i) == DBNull.Value;
1324 if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
1328 moreResults = command.Tds.NextResult ();
1329 } catch (TdsInternalException ex) {
1330 command.Connection.Close ();
1331 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
1334 command.GetOutputParameters ();
1336 // new schema - don't do anything except reset schemaTable as command.Tds.Columns is already updated
1338 dataTypeNames = null;
1354 if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
1356 if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
1361 if ((haveRead) && (!readResultUsed))
1363 readResultUsed = true;
1366 return (ReadRecord ());
1369 internal bool ReadRecord ()
1372 bool result = command.Tds.NextRow ();
1376 } catch (TdsInternalException ex) {
1377 command.Connection.Close ();
1378 throw SqlException.FromTdsInternalException ((TdsInternalException) ex);
1382 void ValidateState ()
1385 throw new InvalidOperationException ("Invalid attempt to read data when reader is closed");
1389 public override Type GetProviderSpecificFieldType (int i)
1391 return (GetSqlValue (i).GetType());
1394 public override object GetProviderSpecificValue (int i)
1396 return (GetSqlValue (i));
1399 public override int GetProviderSpecificValues (object [] values)
1401 return (GetSqlValues (values));
1404 public virtual SqlBytes GetSqlBytes (int i)
1406 //object value = GetSqlValue (i);
1407 //if (!(value is SqlBinary))
1408 // throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
1409 Byte[] val = (byte[])GetValue(i);
1410 SqlBytes sb = new SqlBytes (val);
1415 #endregion // Methods