Jeff Smith Blog

Random Thoughts & Cartesian Products with Microsoft SQL Server

DataViewReader Class


 public class DataViewReaderIDataReader
    {
        DataView _source;
        IEnumerator _enum;
        bool _closed = true;
 
        public DataViewReader(DataView source)
        {
            _source = source;
        }
 
        DataRowView current
        {
            get
            {
                return (DataRowView)_enum.Current;
            }
        }
 
        #region IDataReader Members
 
        public void Close()
        {
            _closed = true;
            return;
        }
 
        public int Depth
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }
 
        public DataTable GetSchemaTable()
        {
            return _source.Table;
        }
 
        public bool IsClosed
        {
            get { return _closed; }
        }
 
        public bool NextResult()
        {
            return false;
        }
 
        public bool Read()
        {
            if (_closed)
                _enum = _source.GetEnumerator();
 
            _closed = false;
            return _enum.MoveNext();
        }
 
        public int RecordsAffected
        {
            get { throw new Exception("The method or operation is not implemented."); }
        }
 
        #endregion
 
        #region IDisposable Members
 
        public void Dispose()
        {
            _source.Dispose();
        }
 
        #endregion
 
        #region IDataRecord Members
 
        public int FieldCount
        {
            get { return _source.Table.Columns.Count; }
        }
 
        public bool GetBoolean(int i)
        {
            return (bool)current[i];
        }
 
        public byte GetByte(int i)
        {
            return (byte)current[i];
        }
 
        public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
        {
            throw new Exception("The method or operation is not implemented.");
        }
 
        public char GetChar(int i)
        {
            return (char)current[i];
        }
 
        public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
        {
            throw new Exception("The method or operation is not implemented.");
        }
 
        public IDataReader GetData(int i)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public string GetDataTypeName(int i)
        {
            return GetFieldType(i).Name;
        }
 
        public DateTime GetDateTime(int i)
        {
            return (DateTime)current[i];
        }
 
        public decimal GetDecimal(int i)
        {
            return (Decimal)current[i];
        }
 
        public double GetDouble(int i)
        {
            return (Double)current[i];
        }
 
        public Type GetFieldType(int i)
        {
            return _source.Table.Columns[i].DataType;
        }
 
        public float GetFloat(int i)
        {
            return (float)current[i];
        }
 
        public Guid GetGuid(int i)
        {
            return (Guid)current[i];
        }
 
        public short GetInt16(int i)
        {
            return (short)current[i];
        }
 
        public int GetInt32(int i)
        {
            return (int)current[i];
        }
 
        public long GetInt64(int i)
        {
            return (long)current[i];
        }
 
        public string GetName(int i)
        {
            return _source.Table.Columns[i].ColumnName;
        }
 
        public int GetOrdinal(string name)
        {
            return _source.Table.Columns[name].Ordinal;
        }
 
        public string GetString(int i)
        {
            return (string)current[i];
        }
 
        public object GetValue(int i)
        {
            return current[i];
        }
 
        public int GetValues(object[] values)
        {
            int count = Math.Min(values.Length, FieldCount);
 
            for (int i = 0; i < count; i++)
                values[i] = current[i];
 
            return count;
        }
 
        public bool IsDBNull(int i)
        {
            return current[i] == DBNull.Value;
        }
 
        public object this[string name]
        {
            get { return current[name]; }
        }
 
        public object this[int i]
        {
            get { return current[i]; }
        }
 
        #endregion
    }

Legacy Comments


Tim
2008-06-15
re: DataViewReader Class
Thank you for that, i was using the view.ToTable.CreateDataReader to pass to your brilliant life saving pivot function, but i was concerned with the performance and wondering if i should just rewrite the pivot to use the dataview (such a surprisingly simple function as well). So this should help immensely.

I just converted it to VB and since it still requires a bit of work after running it through the online converter (adding the Implements IDataReader.* after each method) i thought id save some other people the same chore, and put it up on pastebin.com (i hope thats ok with you, i did put a pointer back to here in the code)

I did notice a problem when using the DataViewReader with the Pivot function when it was getting the data type for the column (the enumerator didnt exist at that point as Read wasn't called). I fixed it by making the following changes to the GetFieldType and GetDataTypeName, making them behave like the DataTableReader does.


public string GetDataTypeName(int i)
{
return GetFieldType(i).Name;
}

public Type GetFieldType(int i)
{
return _source.Table.Columns.Item(i).DataType;
}


For anybody that wants it, the VB version (with above changes) is at http://pastebin.com/f7417cd90

Jeff
2008-06-16
re: DataViewReader Class
Tim -- you are right on the money with those changes; thank you for posting them for me. I hadn't tested those two properties. I've updated the code with your changes.

Thanks again!!
- Jeff

Lukasz
2010-09-14
re: DataViewReader Class
I had trouble in VS 2010 IEnumerator _enum. It told me that the generic IEnumerator<T> was missing an argument. So I did the following (and it all worked)?

Changed:
IEnumerator _enum;

To:
IEnumerator<Object> _enum;

Changed:
_enum = _source.GetEnumerator();

To:
_enum = (IEnumerator<object>)_source.GetEnumerator();

Works like a charm. Very nice little class.
-Lukasz