PageRenderTime 33ms CodeModel.GetById 10ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Rhino.Etl.Core/DataReaders/EnumerableDataReader.cs

http://github.com/ayende/rhino-etl
C# | 447 lines | 178 code | 40 blank | 229 comment | 8 complexity | f0edbddb56b33edbece088ec97c6a1df MD5 | raw file
  1namespace Rhino.Etl.Core.DataReaders
  2{
  3    using System;
  4    using System.Collections;
  5    using System.Collections.Generic;
  6    using System.Data;
  7
  8    /// <summary>
  9    /// Represent a data reader that is based on IEnumerable implementation.
 10    /// This is important because we can now pass an in memory generated code to code
 11    /// that requires this, such as the SqlBulkCopy class.
 12    /// </summary>
 13    public abstract class EnumerableDataReader : IDataReader
 14    {
 15        /// <summary>
 16        /// The enumerator that we are iterating on.
 17        /// Required so subclasses can access the current object.
 18        /// </summary>
 19        protected readonly IEnumerator enumerator;
 20        private long rowCount = 0;
 21        private bool isClosed = false;
 22
 23        /// <summary>
 24        /// Initializes a new instance of the <see cref="EnumerableDataReader"/> class.
 25        /// </summary>
 26        /// <param name="enumerator">The enumerator.</param>
 27        protected EnumerableDataReader(IEnumerator enumerator)
 28        {
 29            this.enumerator = enumerator;
 30        }
 31
 32        /// <summary>
 33        /// Gets the descriptors for the properties that this instance
 34        /// is going to handle
 35        /// </summary>
 36        /// <value>The property descriptors.</value>
 37        protected abstract IList<Descriptor> PropertyDescriptors { get; }
 38
 39        #region IDataReader Members
 40
 41        /// <summary>
 42        /// Closes the <see cref="T:System.Data.IDataReader"/> Object.
 43        /// </summary>
 44        public void Close()
 45        {
 46            DoClose();
 47            isClosed = true;
 48        }
 49
 50        /// <summary>
 51        /// Perform the actual closing of the reader
 52        /// </summary>
 53        protected abstract void DoClose();
 54
 55        /// <summary>
 56        /// Returns a <see cref="T:System.Data.DataTable"/> that describes the column metadata of the <see cref="T:System.Data.IDataReader"/>.
 57        /// </summary>
 58        /// <remarks>
 59        /// This is a very trivial implementation, anything that tries to do something really fancy with it
 60        /// may need more information
 61        /// </remarks>
 62        /// <returns>
 63        /// A <see cref="T:System.Data.DataTable"/> that describes the column metadata.
 64        /// </returns>
 65        public DataTable GetSchemaTable()
 66        {
 67            DataTable table = new DataTable("schema");
 68            table.Columns.Add("ColumnName", typeof(string));
 69            table.Columns.Add("ColumnOrdinal", typeof(int));
 70            table.Columns.Add("DataType", typeof(Type));
 71
 72            for (int i = 0; i < PropertyDescriptors.Count; i++)
 73            {
 74                table.Rows.Add(
 75                    PropertyDescriptors[i].Name,
 76                    i,
 77                    PropertyDescriptors[i].Type
 78                    );
 79            }
 80            return table;
 81        }
 82
 83        /// <summary>
 84        /// We do not support mutliply result set
 85        /// </summary>
 86        /// <returns>
 87        /// true if there are more rows; otherwise, false.
 88        /// </returns>
 89        public bool NextResult()
 90        {
 91            return false;
 92        }
 93
 94        /// <summary>
 95        /// Advances the <see cref="T:System.Data.IDataReader"/> to the next record.
 96        /// </summary>
 97        /// <returns>
 98        /// true if there are more rows; otherwise, false.
 99        /// </returns>
100        public bool Read()
101        {
102            bool next = enumerator.MoveNext();
103            if (next)
104                rowCount += 1;
105            return next;
106        }
107
108        /// <summary>
109        /// Gets a value indicating the depth of nesting for the current row.
110        /// We do not support nesting.
111        /// </summary>
112        /// <value></value>
113        /// <returns>The level of nesting.</returns>
114        public int Depth
115        {
116            get { return 0; }
117        }
118
119        /// <summary>
120        /// Gets a value indicating whether the data reader is closed.
121        /// </summary>
122        /// <value></value>
123        /// <returns>true if the data reader is closed; otherwise, false.</returns>
124        public bool IsClosed
125        {
126            get { return isClosed; }
127        }
128
129        /// <summary>
130        /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement.
131        /// </summary>
132        /// <value></value>
133        /// <returns>The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement failed; and -1 for SELECT statements.</returns>
134        public int RecordsAffected
135        {
136            get { return -1; }
137        }
138
139        /// <summary>
140        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
141        /// </summary>
142        public void Dispose()
143        {
144            Close();
145        }
146
147        /// <summary>
148        /// Gets the name for the field to find.
149        /// </summary>
150        /// <param name="i">The index of the field to find.</param>
151        /// <returns>
152        /// The name of the field or the empty string (""), if there is no value to return.
153        /// </returns>
154        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
155        public string GetName(int i)
156        {
157            return PropertyDescriptors[i].Name;
158        }
159
160        /// <summary>
161        /// Gets the data type information for the specified field.
162        /// </summary>
163        /// <param name="i">The index of the field to find.</param>
164        /// <returns>
165        /// The data type information for the specified field.
166        /// </returns>
167        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
168        public string GetDataTypeName(int i)
169        {
170            return PropertyDescriptors[i].Type.Name;
171        }
172
173        /// <summary>
174        /// Gets the <see cref="T:System.Type"/> information corresponding to the type of <see cref="T:System.Object"/> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)"/>.
175        /// </summary>
176        /// <param name="i">The index of the field to find.</param>
177        /// <returns>
178        /// The <see cref="T:System.Type"/> information corresponding to the type of <see cref="T:System.Object"/> that would be returned from <see cref="M:System.Data.IDataRecord.GetValue(System.Int32)"/>.
179        /// </returns>
180        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
181        public Type GetFieldType(int i)
182        {
183            return PropertyDescriptors[i].Type;
184        }
185
186        /// <summary>
187        /// Return the value of the specified field.
188        /// </summary>
189        /// <param name="i">The index of the field to find.</param>
190        /// <returns>
191        /// The <see cref="T:System.Object"/> which will contain the field value upon return.
192        /// </returns>
193        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
194        public object GetValue(int i)
195        {
196            return PropertyDescriptors[i].GetValue(enumerator.Current) ?? DBNull.Value;
197        }
198
199        /// <summary>
200        /// Gets all the attribute fields in the collection for the current record.
201        /// </summary>
202        /// <param name="values">An array of <see cref="T:System.Object"/> to copy the attribute fields into.</param>
203        /// <returns>
204        /// The number of instances of <see cref="T:System.Object"/> in the array.
205        /// </returns>
206        public int GetValues(object[] values)
207        {
208            for (int i = 0; i < PropertyDescriptors.Count; i++)
209            {
210                values[i] = PropertyDescriptors[i].GetValue(enumerator.Current);
211            }
212            return PropertyDescriptors.Count;
213        }
214
215        /// <summary>
216        /// Return the index of the named field.
217        /// </summary>
218        /// <param name="name">The name of the field to find.</param>
219        /// <returns>The index of the named field.</returns>
220        public int GetOrdinal(string name)
221        {
222            for (int i = 0; i < PropertyDescriptors.Count; i++)
223            {
224                if (string.Equals(PropertyDescriptors[i].Name, name, StringComparison.InvariantCultureIgnoreCase))
225                    return i;
226            }
227            throw new ArgumentException("There is not property with name: " + name);
228        }
229
230        /// <summary>
231        /// Gets the value of the specified column as a Boolean.
232        /// </summary>
233        /// <param name="i">The zero-based column ordinal.</param>
234        /// <returns>The value of the column.</returns>
235        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
236        public bool GetBoolean(int i)
237        {
238            return (bool)GetValue(i);
239        }
240
241        /// <summary>
242        /// Gets the 8-bit unsigned integer value of the specified column.
243        /// </summary>
244        /// <param name="i">The zero-based column ordinal.</param>
245        /// <returns>
246        /// The 8-bit unsigned integer value of the specified column.
247        /// </returns>
248        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
249        public byte GetByte(int i)
250        {
251            return (byte)GetValue(i);
252        }
253
254        /// <summary>
255        /// We do not support this operation
256        /// </summary>
257        public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
258        {
259            throw new NotSupportedException();
260        }
261
262        /// <summary>
263        /// Gets the character value of the specified column.
264        /// </summary>
265        /// <param name="i">The zero-based column ordinal.</param>
266        /// <returns>
267        /// The character value of the specified column.
268        /// </returns>
269        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
270        public char GetChar(int i)
271        {
272            return (char)GetValue(i);
273        }
274
275        /// <summary>
276        /// We do not support this operation
277        /// </summary>
278        public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
279        {
280            throw new NotSupportedException();
281        }
282
283        /// <summary>
284        /// Returns the GUID value of the specified field.
285        /// </summary>
286        /// <param name="i">The index of the field to find.</param>
287        /// <returns>The GUID value of the specified field.</returns>
288        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
289        public Guid GetGuid(int i)
290        {
291            return (Guid)GetValue(i);
292        }
293
294        /// <summary>
295        /// Gets the 16-bit signed integer value of the specified field.
296        /// </summary>
297        /// <param name="i">The index of the field to find.</param>
298        /// <returns>
299        /// The 16-bit signed integer value of the specified field.
300        /// </returns>
301        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
302        public short GetInt16(int i)
303        {
304            return (short)GetValue(i);
305        }
306
307        /// <summary>
308        /// Gets the 32-bit signed integer value of the specified field.
309        /// </summary>
310        /// <param name="i">The index of the field to find.</param>
311        /// <returns>
312        /// The 32-bit signed integer value of the specified field.
313        /// </returns>
314        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
315        public int GetInt32(int i)
316        {
317            return (int)GetValue(i);
318        }
319
320        /// <summary>
321        /// Gets the 64-bit signed integer value of the specified field.
322        /// </summary>
323        /// <param name="i">The index of the field to find.</param>
324        /// <returns>
325        /// The 64-bit signed integer value of the specified field.
326        /// </returns>
327        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
328        public long GetInt64(int i)
329        {
330            return (long)GetValue(i);
331        }
332
333        /// <summary>
334        /// Gets the single-precision floating point number of the specified field.
335        /// </summary>
336        /// <param name="i">The index of the field to find.</param>
337        /// <returns>
338        /// The single-precision floating point number of the specified field.
339        /// </returns>
340        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
341        public float GetFloat(int i)
342        {
343            return (float)GetValue(i);
344        }
345
346        /// <summary>
347        /// Gets the double-precision floating point number of the specified field.
348        /// </summary>
349        /// <param name="i">The index of the field to find.</param>
350        /// <returns>
351        /// The double-precision floating point number of the specified field.
352        /// </returns>
353        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
354        public double GetDouble(int i)
355        {
356            return (double)GetValue(i);
357        }
358
359        /// <summary>
360        /// Gets the string value of the specified field.
361        /// </summary>
362        /// <param name="i">The index of the field to find.</param>
363        /// <returns>The string value of the specified field.</returns>
364        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
365        public string GetString(int i)
366        {
367            return (string)GetValue(i);
368        }
369
370        /// <summary>
371        /// Gets the fixed-position numeric value of the specified field.
372        /// </summary>
373        /// <param name="i">The index of the field to find.</param>
374        /// <returns>
375        /// The fixed-position numeric value of the specified field.
376        /// </returns>
377        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
378        public decimal GetDecimal(int i)
379        {
380            return (decimal)GetValue(i);
381        }
382
383        /// <summary>
384        /// Gets the date and time data value of the specified field.
385        /// </summary>
386        /// <param name="i">The index of the field to find.</param>
387        /// <returns>
388        /// The date and time data value of the specified field.
389        /// </returns>
390        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
391        public DateTime GetDateTime(int i)
392        {
393            return (DateTime)GetValue(i);
394        }
395
396        /// <summary>
397        /// We do not support nesting
398        /// </summary>
399        public IDataReader GetData(int i)
400        {
401            throw new NotSupportedException();
402        }
403
404        /// <summary>
405        /// Return whether the specified field is set to null.
406        /// </summary>
407        /// <param name="i">The index of the field to find.</param>
408        /// <returns>
409        /// true if the specified field is set to null; otherwise, false.
410        /// </returns>
411        /// <exception cref="T:System.IndexOutOfRangeException">The index passed was outside the range of 0 through <see cref="P:System.Data.IDataRecord.FieldCount"/>. </exception>
412        public bool IsDBNull(int i)
413        {
414            return GetValue(i) == null || GetValue(i) == DBNull.Value;
415        }
416
417        /// <summary>
418        /// Gets the number of columns in the current row.
419        /// </summary>
420        /// <value></value>
421        /// <returns>When not positioned in a valid recordset, 0; otherwise, the number of columns in the current record. The default is -1.</returns>
422        public int FieldCount
423        {
424            get { return PropertyDescriptors.Count; }
425        }
426
427        /// <summary>
428        /// Gets the <see cref="System.Object"/> with the specified i.
429        /// </summary>
430        /// <value></value>
431        public object this[int i]
432        {
433            get { return GetValue(i); }
434        }
435
436        /// <summary>
437        /// Gets the <see cref="System.Object"/> with the specified name.
438        /// </summary>
439        /// <value></value>
440        public object this[string name]
441        {
442            get { return GetValue(GetOrdinal(name)); }
443        }
444
445        #endregion
446    }
447}