/// <summary> /// Execute a command against a data source, mapping the data reader to an enumerable of record dictionaries. /// This method perfoms LAZY LOADING/DEFERRED EXECUTION. /// Note that THE DATA READER WILL NOT BE DISPOSED UPON ENUMERATION OR FOREACH BRANCH OUT. /// </summary> /// <param name="dbDataReader"> The target data reader. </param> /// <param name="recordsAffectedCallback"> Executed when the output count of records affected is available to return (post enumeration). </param> /// <returns> An enumerable of record dictionary instances, containing key/value pairs of data. </returns> public IEnumerable <IAdoNetStreamingRecord> GetRecordsFromReader(DbDataReader dbDataReader, Action <int> recordsAffectedCallback) { AdoNetStreamingRecord record; int recordsAffected; long recordIndex = 0; string key; object value; Guid _ = this.__enter(); if ((object)dbDataReader == null) { throw new ArgumentNullException(nameof(dbDataReader)); } //using (this.__use(_, dbDataReader)) { this.__trace(_, "before yield loop"); while (dbDataReader.Read()) { record = new AdoNetStreamingRecord(-1, recordIndex); for (int fieldIndex = 0; fieldIndex < dbDataReader.FieldCount; fieldIndex++) { key = dbDataReader.GetName(fieldIndex); value = dbDataReader.GetValue(fieldIndex); value = value.ChangeType <object>(); if (record.ContainsKey(key) || (key ?? string.Empty).Length == 0) { key = string.Format("Field_{0:0000}", fieldIndex); } record.Add(key, value); } this.__trace(_, "on yield item"); recordIndex++; yield return(record); // LAZY PROCESSING INTENT HERE / DO NOT FORCE EAGER LOAD } this.__trace(_, "after yield loop"); //this.__disp(_, dbDataReader); } recordsAffected = dbDataReader.RecordsAffected; if ((object)recordsAffectedCallback != null) { recordsAffectedCallback(recordsAffected); } this.__leave(_); }
/// <summary> /// Execute a command against a data source, mapping the data reader GetSchemaTable() result to an enumerable of record dictionaries. /// This method perfoms LAZY LOADING/DEFERRED EXECUTION. /// Note that THE DATA READER WILL NOT BE DISPOSED UPON ENUMERATION OR FOREACH BRANCH OUT. /// </summary> /// <param name="dbDataReader"> The target data reader. </param> /// <param name="recordsAffectedCallback"> Executed when the output count of records affected is available to return (post enumeration). </param> /// <returns> An enumerable of record dictionary instances, containing key/value pairs of schema metadata. </returns> public IEnumerable <IAdoNetStreamingRecord> GetSchemaRecordsFromReader(DbDataReader dbDataReader, Action <int> recordsAffectedCallback) { ReadOnlyCollection <DbColumn> dbColumns; DbColumn dbColumn; PropertyInfo[] propertyInfos; PropertyInfo propertyInfo; AdoNetStreamingRecord record; int recordsAffected; string key; object value; Guid _ = this.__enter(); if ((object)dbDataReader == null) { throw new ArgumentNullException(nameof(dbDataReader)); } if (!dbDataReader.CanGetColumnSchema()) { throw new NotSupportedException(string.Format("The connection command type '{0}' does not support schema access.", dbDataReader.GetType().FullName)); } //using (this.__use(_, dbDataReader)) { dbColumns = dbDataReader.GetColumnSchema(); this.__trace(_, "before yield loop"); if ((object)dbColumns != null) { for (long recordIndex = 0; recordIndex < dbColumns.Count; recordIndex++) { dbColumn = dbColumns[(int)recordIndex]; propertyInfos = dbColumn.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty); record = new AdoNetStreamingRecord(-1, recordIndex); if ((object)propertyInfos != null) { for (int fieldIndex = 0; fieldIndex < propertyInfos.Length; fieldIndex++) { propertyInfo = propertyInfos[fieldIndex]; if (propertyInfo.GetIndexParameters().Any()) { continue; } key = propertyInfo.Name; value = propertyInfo.GetValue(dbColumn); value = value.ChangeType <object>(); record.Add(key, value); } } this.__trace(_, "on yield item"); yield return(record); // LAZY PROCESSING INTENT HERE / DO NOT FORCE EAGER LOAD } } this.__trace(_, "after yield loop"); //this.__disp(_, dbDataReader); } recordsAffected = dbDataReader.RecordsAffected; if ((object)recordsAffectedCallback != null) { recordsAffectedCallback(recordsAffected); } this.__leave(_); }