/// <summary> /// Gets one instance of <typeparamref name="T"/> from data reader. /// </summary> /// <typeparam name="T">Type of an instance.</typeparam> /// <param name="reader">Source data reader.</param> /// <param name="ctorParamMappings">Column constructor parameter mappings.</param> /// <param name="propMappings">Property column mappings.</param> /// <param name="breakAfterFirst">true to break after the first read record; false to not. if false throws exception if more than one record.</param> /// <returns>A single instance read from reader or null.</returns> private static T GetInstance <T>(DbDataReader reader, ColumnConstructorParameterMappingCollection <T> ctorParamMappings, IEnumerable <PropertyColumnMapping> propMappings, bool breakAfterFirst) where T : class { T instance = null; if (reader.HasRows) { //// create activator to create instance with constructor var activator = ActivatorFactory.GetActivator <T>(ctorParamMappings.Constructor); Dictionary <string, int> propertyColumnLookupTable = null; //// if contains property mappings, get lookup table if (propMappings != null) { propertyColumnLookupTable = GetColumnIndexLookupTable(reader, propMappings.Select(x => x.ColumnName)); } /// mappings between ctor params and columns var ctorColumnLookupTable = GetColumnIndexLookupTable(reader, ctorParamMappings.Select(x => x.ColumnName)); bool first = true; while (reader.Read()) { if (!first) { throw new InvalidOperationException("Reader contains more than expected 1 record."); } object[] arguments = null; //// get constructor arguments if (ctorParamMappings.HasParameters) { arguments = GetConstructorParameters(reader, ctorColumnLookupTable, ctorParamMappings); } //// create instance instance = activator.Invoke(arguments); //// if contains property mappings, read values if (propMappings != null) { ReadData(instance, reader, propMappings, propertyColumnLookupTable); } if (breakAfterFirst) { break; } first = false; } } return(instance); }
/// <summary> /// Gets all instances from data reader. /// </summary> /// <typeparam name="T">Type of an object read.</typeparam> /// <param name="reader">The source <see cref="DbDataReader"/> instance.</param> /// <param name="ctorMappings">The mappings between constructor arguments and columns.</param> /// <param name="propMappings">The mappings between properties and columns.</param> /// <returns>A enumerable of <typeparamref name="T"/> instances.</returns> public static IEnumerable <T> GetRecords <T>(this DbDataReader reader, ColumnConstructorParameterMappingCollection <T> ctorMappings, IEnumerable <PropertyColumnMapping> propMappings) where T : class { if (reader == null) { throw new ArgumentNullException("reader"); } if (ctorMappings == null) { throw new ArgumentNullException("ctorMappings"); } var result = new List <T>(); if (reader.HasRows) { var activator = ActivatorFactory.GetActivator <T>(ctorMappings.Constructor); Dictionary <string, int> propertyColumnLookupTable = null; //// if contains property mappings, get lookup table if (propMappings != null) { propertyColumnLookupTable = GetColumnIndexLookupTable(reader, propMappings.Select(x => x.ColumnName)); } /// mappings between ctor params and columns var ctorColumnLookupTable = GetColumnIndexLookupTable(reader, ctorMappings.Select(x => x.ColumnName)); while (reader.Read()) { object[] arguments = null; //// get constructor arguments if (ctorMappings.HasParameters) { arguments = GetConstructorParameters(reader, ctorColumnLookupTable, ctorMappings); } var instance = activator.Invoke(arguments); //// if contains property mappings, read values if (propMappings != null) { ReadData(instance, reader, propMappings, propertyColumnLookupTable); } result.Add(instance); } } return(result); }