2004-08-12 Sureshkumar T <tsureshkumar@novell.com>
[mono.git] / mcs / class / System.Data / System.Data.SqlClient / SqlDataReader.cs
index 682e9ea8d72de6e03cbdee0e54d763c6e75ff0f7..5e1c293e87b4cc2406bc9030926d70977a840129 100644 (file)
 //
 // Author:
 //   Rodrigo Moya (rodrigo@ximian.com)
+//   Daniel Morgan (danmorg@sc.rr.com)
+//   Tim Coleman (tim@timcoleman.com)
 //
-// (C) Ximian, Inc
+// (C) Ximian, Inc 2002
+// (C) Daniel Morgan 2002
+// Copyright (C) Tim Coleman, 2002
 //
 
-namespace System.Data.SqlClient
-{
-       /// <summary>
-       /// Provides a means of reading one or more forward-only streams of result sets obtained by executing a command at a SQL database.
-       /// </summary>
-       public interface SqlDataReader : IDataReader
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using Mono.Data.Tds.Protocol;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Data;
+using System.Data.Common;
+using System.Data.SqlTypes;
+
+namespace System.Data.SqlClient {
+       public sealed class SqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
        {
-               void Close();
-               
-               DataTable GetSchemaTable();
+               #region Fields
+
+               SqlCommand command;
+               ArrayList dataTypeNames;
+               bool disposed = false;
+               int fieldCount;
+               bool isClosed;
+               bool isSelect;
+               bool moreResults;
+               int resultsRead;
+               int rowsRead;
+               DataTable schemaTable;
+               bool hasRows;
+               bool haveRead;
+               bool readResult;
+               bool readResultUsed;
+
+               #endregion // Fields
+
+               #region Constructors
+
+               internal SqlDataReader (SqlCommand command)
+               {
+                       readResult = false;
+                       haveRead = false;
+                       readResultUsed = false;
+                       this.command = command;
+                       schemaTable = ConstructSchemaTable ();
+                       resultsRead = 0;
+                       fieldCount = 0;
+                       isClosed = false;
+                       isSelect = (command.CommandText.Trim ().ToUpper ().StartsWith ("SELECT"));
+                       command.Tds.RecordsAffected = 0;
+                       NextResult ();
+               }
+
+               #endregion // Constructors
+
+               #region Properties
+
+               public int Depth {
+                       get { return 0; }
+               }
+
+               public int FieldCount {
+                       get { return fieldCount; }
+               }
+
+               public bool IsClosed {
+                       get { return isClosed; }
+               }
+
+               public object this [int i] {
+                       get { return GetValue (i); }
+               }
+
+               public object this [string name] {
+                       get { return GetValue (GetOrdinal (name)); }
+               }
+       
+               public int RecordsAffected {
+                       get { 
+                               if (isSelect) 
+                                       return -1;
+                               else
+                                       return command.Tds.RecordsAffected; 
+                       }
+               }
+
+               public bool HasRows {
+                       get {
+                               if (haveRead) 
+                                       return readResult;
+                       
+                               haveRead = true;
+                               readResult = ReadRecord ();
+                               return readResult;                                              
+                       }
+               }
+       
+               #endregion // Properties
+
+               #region Methods
+
+               public void Close ()
+               {
+                       // skip to end & read output parameters.
+                       while (NextResult ())
+                               ;
+                       isClosed = true;
+                       command.Connection.DataReader = null;
+                       command.CloseDataReader (moreResults);
+               }
+
+               private static DataTable ConstructSchemaTable ()
+               {
+                       Type booleanType = Type.GetType ("System.Boolean");
+                       Type stringType = Type.GetType ("System.String");
+                       Type intType = Type.GetType ("System.Int32");
+                       Type typeType = Type.GetType ("System.Type");
+                       Type shortType = Type.GetType ("System.Int16");
+
+                       DataTable schemaTable = new DataTable ("SchemaTable");
+                       schemaTable.Columns.Add ("ColumnName", stringType);
+                       schemaTable.Columns.Add ("ColumnOrdinal", intType);
+                       schemaTable.Columns.Add ("ColumnSize", intType);
+                       schemaTable.Columns.Add ("NumericPrecision", shortType);
+                       schemaTable.Columns.Add ("NumericScale", shortType);
+                       schemaTable.Columns.Add ("IsUnique", booleanType);
+                       schemaTable.Columns.Add ("IsKey", booleanType);
+                       schemaTable.Columns.Add ("BaseServerName", stringType);
+                       schemaTable.Columns.Add ("BaseCatalogName", stringType);
+                       schemaTable.Columns.Add ("BaseColumnName", stringType);
+                       schemaTable.Columns.Add ("BaseSchemaName", stringType);
+                       schemaTable.Columns.Add ("BaseTableName", stringType);
+                       schemaTable.Columns.Add ("DataType", typeType);
+                       schemaTable.Columns.Add ("AllowDBNull", booleanType);
+                       schemaTable.Columns.Add ("ProviderType", intType);
+                       schemaTable.Columns.Add ("IsAliased", booleanType);
+                       schemaTable.Columns.Add ("IsExpression", booleanType);
+                       schemaTable.Columns.Add ("IsIdentity", booleanType);
+                       schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
+                       schemaTable.Columns.Add ("IsRowVersion", booleanType);
+                       schemaTable.Columns.Add ("IsHidden", booleanType);
+                       schemaTable.Columns.Add ("IsLong", booleanType);
+                       schemaTable.Columns.Add ("IsReadOnly", booleanType);
+
+                       return schemaTable;
+               }
+
+               private void Dispose (bool disposing) 
+               {
+                       if (!disposed) {
+                               if (disposing) {
+                                       schemaTable.Dispose ();
+                                       Close ();
+                                       command = null;
+                               }
+                               disposed = true;
+                       }
+               }
+
+               public bool GetBoolean (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is bool)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (bool) value;
+               }
+
+               public byte GetByte (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is byte)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (byte) value;
+               }
+
+               public long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
+               {
+                       object value = GetValue (i);
+                       if (!(value is byte [])) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       
+                       if ( buffer == null ) {
+                               // Return length of data
+                               return ((byte []) value).Length;
+                       }
+                       else {
+                               // Copy data into buffer
+                               Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
+                               return ((byte []) value).Length - dataIndex;
+                       }
+               }
+                                                                                                    
+               [EditorBrowsableAttribute (EditorBrowsableState.Never)]
+               public char GetChar (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is char)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (char) value;
+               }
+
+               public long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
+               {
+                       object value = GetValue (i);
+                       char [] valueBuffer;
+                       
+                       if (value is char[])
+                               valueBuffer = (char[])value;
+                       else if (value is string)
+                               valueBuffer = ((string)value).ToCharArray();
+                       else {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       
+                       if ( buffer == null ) {
+                               // Return length of data
+                               return valueBuffer.Length;
+                       }
+                       else {
+                               // Copy data into buffer
+                               Array.Copy (valueBuffer, (int) dataIndex, buffer, bufferIndex, length);
+                               return valueBuffer.Length - dataIndex;
+                       }
+               }
                
-               bool NextResult();
+               [EditorBrowsableAttribute (EditorBrowsableState.Never)] 
+               public IDataReader GetData (int i)
+               {
+                       return ( (IDataReader) this [i]);
+               }
+
+               public string GetDataTypeName (int i)
+               {
+                       return (string) dataTypeNames [i];
+               }
+
+               public DateTime GetDateTime (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is DateTime)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               else throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (DateTime) value;
+               }
+
+               public decimal GetDecimal (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is decimal)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (decimal) value;
+               }
+
+               public double GetDouble (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is double)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (double) value;
+               }
+
+               public Type GetFieldType (int i)
+               {
+                       return (Type) schemaTable.Rows[i]["DataType"];
+               }
+
+               public float GetFloat (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is float)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (float) value;
+               }
+
+               public Guid GetGuid (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is Guid)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (Guid) value;
+               }
+
+               public short GetInt16 (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is short)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (short) value;
+               }
+
+               public int GetInt32 (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is int)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (int) value;
+               }
+
+               public long GetInt64 (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is long)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (long) value;
+               }
+
+               public string GetName (int i)
+               {
+                       return (string) schemaTable.Rows[i]["ColumnName"];
+               }
+
+               public int GetOrdinal (string name)
+               {
+                       foreach (DataRow schemaRow in schemaTable.Rows)
+                               if (((string) schemaRow ["ColumnName"]).Equals (name))
+                                       return (int) schemaRow ["ColumnOrdinal"];
+                       foreach (DataRow schemaRow in schemaTable.Rows)
+                               if (String.Compare (((string) schemaRow ["ColumnName"]), name, true) == 0)
+                                       return (int) schemaRow ["ColumnOrdinal"];
+                       throw new IndexOutOfRangeException ();
+               }
+
+               public DataTable GetSchemaTable ()
+               {
+                       if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
+                               return schemaTable;
+
+                       if (!moreResults)
+                               return null;
 
-               bool Read();
+                       fieldCount = 0;
 
-               int Depth{get;}
+                       dataTypeNames = new ArrayList ();
 
-               bool IsClosed{get;}
+                       foreach (TdsDataColumn schema in command.Tds.Columns) {
+                               DataRow row = schemaTable.NewRow ();
 
-               int RecordsAffected{get;}
+                               row ["ColumnName"]              = GetSchemaValue (schema, "ColumnName");
+                               row ["ColumnSize"]              = GetSchemaValue (schema, "ColumnSize"); 
+                               row ["ColumnOrdinal"]           = GetSchemaValue (schema, "ColumnOrdinal");
+                               row ["NumericPrecision"]        = GetSchemaValue (schema, "NumericPrecision");
+                               row ["NumericScale"]            = GetSchemaValue (schema, "NumericScale");
+                               row ["IsUnique"]                = GetSchemaValue (schema, "IsUnique");
+                               row ["IsKey"]                   = GetSchemaValue (schema, "IsKey");
+                               row ["BaseServerName"]          = GetSchemaValue (schema, "BaseServerName");
+                               row ["BaseCatalogName"]         = GetSchemaValue (schema, "BaseCatalogName");
+                               row ["BaseColumnName"]          = GetSchemaValue (schema, "BaseColumnName");
+                               row ["BaseSchemaName"]          = GetSchemaValue (schema, "BaseSchemaName");
+                               row ["BaseTableName"]           = GetSchemaValue (schema, "BaseTableName");
+                               row ["AllowDBNull"]             = GetSchemaValue (schema, "AllowDBNull");
+                               row ["IsAliased"]               = GetSchemaValue (schema, "IsAliased");
+                               row ["IsExpression"]            = GetSchemaValue (schema, "IsExpression");
+                               row ["IsIdentity"]              = GetSchemaValue (schema, "IsIdentity");
+                               row ["IsAutoIncrement"]         = GetSchemaValue (schema, "IsAutoIncrement");
+                               row ["IsRowVersion"]            = GetSchemaValue (schema, "IsRowVersion");
+                               row ["IsHidden"]                = GetSchemaValue (schema, "IsHidden");
+                               row ["IsReadOnly"]              = GetSchemaValue (schema, "IsReadOnly");
 
+                               // We don't always get the base column name.
+                               if (row ["BaseColumnName"] == DBNull.Value)
+                                       row ["BaseColumnName"] = row ["ColumnName"];
+
+                               switch ((TdsColumnType) schema ["ColumnType"]) {
+                                       case TdsColumnType.Int1:
+                                       case TdsColumnType.Int2:
+                                       case TdsColumnType.Int4:
+                                       case TdsColumnType.IntN:
+                                               switch ((int) schema ["ColumnSize"]) {
+                                               case 1:
+                                                       dataTypeNames.Add ("tinyint");
+                                                       row ["ProviderType"] = (int) SqlDbType.TinyInt;
+                                                       row ["DataType"] = typeof (byte);
+                                                       row ["IsLong"] = false;
+                                                       break;
+                                               case 2:
+                                                       dataTypeNames.Add ("smallint");
+                                                       row ["ProviderType"] = (int) SqlDbType.SmallInt;
+                                                       row ["DataType"] = typeof (short);
+                                                       row ["IsLong"] = false;
+                                                       break;
+                                               case 4:
+                                                       dataTypeNames.Add ("int");
+                                                       row ["ProviderType"] = (int) SqlDbType.Int;
+                                                       row ["DataType"] = typeof (int);
+                                                       row ["IsLong"] = false;
+                                                       break;
+                                               case 8:
+                                                       dataTypeNames.Add ("bigint");
+                                                       row ["ProviderType"] = (int) SqlDbType.BigInt;
+                                                       row ["DataType"] = typeof (long);
+                                                       row ["IsLong"] = false;
+                                                       break;
+                                               }
+                                               break;
+                                       case TdsColumnType.Real:
+                                       case TdsColumnType.Float8:
+                                       case TdsColumnType.FloatN:
+                                               switch ((int) schema ["ColumnSize"]) {
+                                               case 4:
+                                                       dataTypeNames.Add ("real");
+                                                       row ["ProviderType"] = (int) SqlDbType.Real;
+                                                       row ["DataType"] = typeof (float);
+                                                       row ["IsLong"] = false;
+                                                       break;
+                                               case 8:
+                                                       dataTypeNames.Add ("float");
+                                                       row ["ProviderType"] = (int) SqlDbType.Float;
+                                                       row ["DataType"] = typeof (double);
+                                                       row ["IsLong"] = false;
+                                                       break;
+                                               }
+                                               break;
+                                       case TdsColumnType.Image :
+                                               dataTypeNames.Add ("image");
+                                               row ["ProviderType"] = (int) SqlDbType.Image;
+                                               row ["DataType"] = typeof (byte[]);
+                                               row ["IsLong"] = true;
+                                               break;
+                                       case TdsColumnType.Text :
+                                               dataTypeNames.Add ("text");
+                                               row ["ProviderType"] = (int) SqlDbType.Text;
+                                               row ["DataType"] = typeof (string);
+                                               row ["IsLong"] = true;
+                                               break;
+                                       case TdsColumnType.UniqueIdentifier :
+                                               dataTypeNames.Add ("uniqueidentifier");
+                                               row ["ProviderType"] = (int) SqlDbType.UniqueIdentifier;
+                                               row ["DataType"] = typeof (Guid);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.VarBinary :
+                                       case TdsColumnType.BigVarBinary :
+                                               dataTypeNames.Add ("varbinary");
+                                               row ["ProviderType"] = (int) SqlDbType.VarBinary;
+                                               row ["DataType"] = typeof (byte[]);
+                                               row ["IsLong"] = true;
+                                               break;
+                                       case TdsColumnType.VarChar :
+                                       case TdsColumnType.BigVarChar :
+                                               dataTypeNames.Add ("varchar");
+                                               row ["ProviderType"] = (int) SqlDbType.VarChar;
+                                               row ["DataType"] = typeof (string);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.Binary :
+                                       case TdsColumnType.BigBinary :
+                                               dataTypeNames.Add ("binary");
+                                               row ["ProviderType"] = (int) SqlDbType.Binary;
+                                               row ["DataType"] = typeof (byte[]);
+                                               row ["IsLong"] = true;
+                                               break;
+                                       case TdsColumnType.Char :
+                                       case TdsColumnType.BigChar :
+                                               dataTypeNames.Add ("char");
+                                               row ["ProviderType"] = (int) SqlDbType.Char;
+                                               row ["DataType"] = typeof (string);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.Bit :
+                                       case TdsColumnType.BitN :
+                                               dataTypeNames.Add ("bit");
+                                               row ["ProviderType"] = (int) SqlDbType.Bit;
+                                               row ["DataType"] = typeof (bool);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.DateTime4 :
+                                       case TdsColumnType.DateTime :
+                                       case TdsColumnType.DateTimeN :
+                                               dataTypeNames.Add ("datetime");
+                                               row ["ProviderType"] = (int) SqlDbType.DateTime;
+                                               row ["DataType"] = typeof (DateTime);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.Money :
+                                       case TdsColumnType.MoneyN :
+                                       case TdsColumnType.Money4 :
+                                               dataTypeNames.Add ("money");
+                                               row ["ProviderType"] = (int) SqlDbType.Money;
+                                               row ["DataType"] = typeof (decimal);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.NText :
+                                               dataTypeNames.Add ("ntext");
+                                               row ["ProviderType"] = (int) SqlDbType.NText;
+                                               row ["DataType"] = typeof (string);
+                                               row ["IsLong"] = true;
+                                               break;
+                                       case TdsColumnType.NVarChar :
+                                               dataTypeNames.Add ("nvarchar");
+                                               row ["ProviderType"] = (int) SqlDbType.NVarChar;
+                                               row ["DataType"] = typeof (string);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.Decimal :
+                                       case TdsColumnType.Numeric :
+                                               dataTypeNames.Add ("decimal");
+                                               row ["ProviderType"] = (int) SqlDbType.Decimal;
+                                               row ["DataType"] = typeof (decimal);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.NChar :
+                                               dataTypeNames.Add ("nchar");
+                                               row ["ProviderType"] = (int) SqlDbType.NChar;
+                                               row ["DataType"] = typeof (string);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       case TdsColumnType.SmallMoney :
+                                               dataTypeNames.Add ("smallmoney");
+                                               row ["ProviderType"] = (int) SqlDbType.SmallMoney;
+                                               row ["DataType"] = typeof (decimal);
+                                               row ["IsLong"] = false;
+                                               break;
+                                       default :
+                                               dataTypeNames.Add ("variant");
+                                               row ["ProviderType"] = (int) SqlDbType.Variant;
+                                               row ["DataType"] = typeof (object);
+                                               row ["IsLong"] = false;
+                                               break;
+                               }
+
+                               schemaTable.Rows.Add (row);
+
+                               fieldCount += 1;
+                       }
+                       return schemaTable;
+               }               
+
+               private static object GetSchemaValue (TdsDataColumn schema, object key)
+               {
+                       if (schema.ContainsKey (key) && schema [key] != null)
+                               return schema [key];
+                       return DBNull.Value;
+               }
+
+               public SqlBinary GetSqlBinary (int i)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public SqlBoolean GetSqlBoolean (int i) 
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlBoolean))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlBoolean) value;
+               }
+
+               public SqlByte GetSqlByte (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlByte))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlByte) value;
+               }
+
+               public SqlDateTime GetSqlDateTime (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlDateTime))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlDateTime) value;
+               }
+
+               public SqlDecimal GetSqlDecimal (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlDecimal))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlDecimal) value;
+               }
+
+               public SqlDouble GetSqlDouble (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlDouble))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlDouble) value;
+               }
+
+               public SqlGuid GetSqlGuid (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlGuid))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlGuid) value;
+               }
+
+               public SqlInt16 GetSqlInt16 (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlInt16))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlInt16) value;
+               }
+
+               public SqlInt32 GetSqlInt32 (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlInt32))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlInt32) value;
+               }
+
+               public SqlInt64 GetSqlInt64 (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlInt64))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlInt64) value;
+               }
+
+               public SqlMoney GetSqlMoney (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlMoney))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlMoney) value;
+               }
+
+               public SqlSingle GetSqlSingle (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlSingle))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlSingle) value;
+               }
+
+               public SqlString GetSqlString (int i)
+               {
+                       object value = GetSqlValue (i);
+                       if (!(value is SqlString))
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       return (SqlString) value;
+               }
+
+               public object GetSqlValue (int i)
+               {
+                       SqlDbType type = (SqlDbType) (schemaTable.Rows [i]["ProviderType"]);
+                       object value = GetValue (i);
+
+                       switch (type) {
+                       case SqlDbType.BigInt:
+                               if (value == DBNull.Value)
+                                       return SqlInt64.Null;
+                               return (SqlInt64) ((long) value);
+                       case SqlDbType.Binary:
+                       case SqlDbType.Image:
+                       case SqlDbType.VarBinary:
+                       case SqlDbType.Timestamp:
+                               if (value == DBNull.Value)
+                                       return SqlBinary.Null;
+                               return (SqlBinary) ((byte[]) value);
+                       case SqlDbType.Bit:
+                               if (value == DBNull.Value)
+                                       return SqlBoolean.Null;
+                               return (SqlBoolean) ((bool) value);
+                       case SqlDbType.Char:
+                       case SqlDbType.NChar:
+                       case SqlDbType.NText:
+                       case SqlDbType.NVarChar:
+                       case SqlDbType.Text:
+                       case SqlDbType.VarChar:
+                               if (value == DBNull.Value)
+                                       return SqlString.Null;
+                               return (SqlString) ((string) value);
+                       case SqlDbType.DateTime:
+                       case SqlDbType.SmallDateTime:
+                               if (value == DBNull.Value)
+                                       return SqlDateTime.Null;
+                               return (SqlDateTime) ((DateTime) value);
+                       case SqlDbType.Decimal:
+                               if (value == DBNull.Value)
+                                       return SqlDecimal.Null;
+                               if (value is TdsBigDecimal)
+                                       return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
+                               return (SqlDecimal) ((decimal) value);
+                       case SqlDbType.Float:
+                               if (value == DBNull.Value)
+                                       return SqlDouble.Null;
+                               return (SqlDouble) ((double) value);
+                       case SqlDbType.Int:
+                               if (value == DBNull.Value)
+                                       return SqlInt32.Null;
+                               return (SqlInt32) ((int) value);
+                       case SqlDbType.Money:
+                       case SqlDbType.SmallMoney:
+                               if (value == DBNull.Value)
+                                       return SqlMoney.Null;
+                               return (SqlMoney) ((decimal) value);
+                       case SqlDbType.Real:
+                               if (value == DBNull.Value)
+                                       return SqlSingle.Null;
+                               return (SqlSingle) ((float) value);
+                       case SqlDbType.UniqueIdentifier:
+                               if (value == DBNull.Value)
+                                       return SqlGuid.Null;
+                               return (SqlGuid) ((Guid) value);
+                       case SqlDbType.SmallInt:
+                               if (value == DBNull.Value)
+                                       return SqlInt16.Null;
+                               return (SqlInt16) ((short) value);
+                       case SqlDbType.TinyInt:
+                               if (value == DBNull.Value)
+                                       return SqlByte.Null;
+                               return (SqlByte) ((byte) value);
+                       }
+
+                       throw new InvalidOperationException ("The type of this column is unknown.");
+               }
+
+               public int GetSqlValues (object[] values)
+               {
+                       int count = 0;
+                       int columnCount = schemaTable.Rows.Count;
+                       int arrayCount = values.Length;
+
+                       if (arrayCount > columnCount)
+                               count = columnCount;
+                       else
+                               count = arrayCount;
+
+                       for (int i = 0; i < count; i += 1) 
+                               values [i] = GetSqlValue (i);
+
+                       return count;
+               }
+
+               public string GetString (int i)
+               {
+                       object value = GetValue (i);
+                       if (!(value is string)) {
+                               if (value is DBNull) throw new SqlNullValueException ();
+                               throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
+                       }
+                       return (string) value;
+               }
+
+               public object GetValue (int i)
+               {
+                       return command.Tds.ColumnValues [i];
+               }
+
+               public int GetValues (object[] values)
+               {
+                       int len = values.Length;
+                       int bigDecimalIndex = command.Tds.ColumnValues.BigDecimalIndex;
+
+                       // If a four-byte decimal is stored, then we can't convert to
+                       // a native type.  Throw an OverflowException.
+                       if (bigDecimalIndex >= 0 && bigDecimalIndex < len)
+                               throw new OverflowException ();
+
+                       command.Tds.ColumnValues.CopyTo (0, values, 0, len);
+                       return (len > FieldCount ? len : FieldCount);
+               }
+
+               void IDisposable.Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return new DbEnumerator (this);
+               }
+
+               public bool IsDBNull (int i)
+               {
+                       return GetValue (i) == DBNull.Value;
+               }
+
+               public bool NextResult ()
+               {
+                       if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
+                               return false;
+
+                       schemaTable.Rows.Clear ();
+
+                       moreResults = command.Tds.NextResult ();
+                       if (!moreResults)
+                               command.GetOutputParameters ();
+
+                       GetSchemaTable ();
+
+                       rowsRead = 0;
+                       resultsRead += 1;
+                       return moreResults;
+               }
+
+               public bool Read ()
+               {
+                       if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
+                               return false;
+                       if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
+                               return false;
+                       if (!moreResults)
+                               return false;
+       
+                       if ((haveRead) && (!readResultUsed))
+                       {
+                               readResultUsed = true;
+                               return true;
+                       }
+                       
+                       
+                       return (ReadRecord ());
+
+               }
+
+               internal bool ReadRecord ()
+               {
+                       
+                       bool result = command.Tds.NextRow ();
+                       
+                       rowsRead += 1;
+                       
+                       return result;
+               }
+                               
+               
 
+               #endregion // Methods
        }
 }