| File: System\Data\Common\DbEnumerator.cs | Web Access |
| Project: src\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj (System.Data.Common) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.ComponentModel; using System.Data.ProviderBase; using System.Diagnostics; namespace System.Data.Common { public class DbEnumerator : IEnumerator { internal IDataReader _reader; internal DbDataRecord? _current; internal SchemaInfo[]? _schemaInfo; // shared schema info among all the data records internal PropertyDescriptorCollection? _descriptors; // cached property descriptors private FieldNameLookup? _fieldNameLookup; private readonly bool _closeReader; // users must get enumerators off of the datareader interfaces public DbEnumerator(IDataReader reader) { if (null == reader) { throw ADP.ArgumentNull(nameof(reader)); } _reader = reader; } public DbEnumerator(IDataReader reader, bool closeReader) { if (null == reader) { throw ADP.ArgumentNull(nameof(reader)); } _reader = reader; _closeReader = closeReader; } public DbEnumerator(DbDataReader reader) : this((IDataReader)reader) { } public DbEnumerator(DbDataReader reader, bool closeReader) : this((IDataReader)reader, closeReader) { } // TODO: this should throw InvalidOperationException if null public object Current => _current!; public bool MoveNext() { if (null == _schemaInfo) { BuildSchemaInfo(); } Debug.Assert(null != _schemaInfo && null != _descriptors, "unable to build schema information!"); _current = null; if (_reader.Read()) { // setup our current record object[] values = new object[_schemaInfo.Length]; _reader.GetValues(values); // this.GetValues() _current = new DataRecordInternal(_schemaInfo, values, _descriptors, _fieldNameLookup!); return true; } if (_closeReader) { _reader.Close(); } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public void Reset() { throw ADP.NotSupported(); } private void BuildSchemaInfo() { int count = _reader.FieldCount; string[] fieldnames = new string[count]; for (int i = 0; i < count; ++i) { fieldnames[i] = _reader.GetName(i); } ADP.BuildSchemaTableInfoTableNames(fieldnames); SchemaInfo[] si = new SchemaInfo[count]; PropertyDescriptor[] props = new PropertyDescriptor[_reader.FieldCount]; for (int i = 0; i < si.Length; i++) { SchemaInfo s = default; s.name = _reader.GetName(i); s.type = _reader.GetFieldType(i); s.typeName = _reader.GetDataTypeName(i); props[i] = new DbColumnDescriptor(i, fieldnames[i], s.type); si[i] = s; } _schemaInfo = si; _fieldNameLookup = new FieldNameLookup(_reader, -1); _descriptors = new PropertyDescriptorCollection(props); } private sealed class DbColumnDescriptor : PropertyDescriptor { private readonly int _ordinal; private readonly Type _type; internal DbColumnDescriptor(int ordinal, string name, Type type) : base(name, null) { _ordinal = ordinal; _type = type; } public override Type ComponentType => typeof(IDataRecord); public override bool IsReadOnly => true; public override Type PropertyType => _type; public override bool CanResetValue(object component) => false; public override object? GetValue(object? component) => ((IDataRecord)component!)[_ordinal]; public override void ResetValue(object component) { throw ADP.NotSupported(); } public override void SetValue(object? component, object? value) { throw ADP.NotSupported(); } public override bool ShouldSerializeValue(object component) => false; } } }