/// <summary> /// Gets a POCO from the data record. /// </summary> /// <param name="dataRequest"> /// The data request. /// </param> /// <param name="entityName"> /// The entity name. /// </param> /// <param name="record"> /// The data record to read. /// </param> /// <typeparam name="T"> /// The type of POCO to generate. /// </typeparam> /// <returns> /// The POCO object as a type of <typeparamref name="T"/>. /// </returns> private static T GetPocoFromReader <T>(PocoDataRequest dataRequest, string entityName, IDataRecord record) { var baseKey = new Tuple <string, PocoDataRequest>(entityName, dataRequest); var baseDirectAttributes = dataRequest.AttributeDefinitions.Where(x => x.IsReferencedDirect).ToList(); var basePocoDelegate = PocoFactories.GetOrAdd( baseKey, key => new Lazy <PocoDelegateInfo>(() => FlatPocoFactory.CreateDelegate(dataRequest, typeof(T), baseDirectAttributes))) .Value; T poco; #if DEBUG try { ////var recordItems = Enumerable.Range(0, record.FieldCount).Select(i => $"{record.GetName(i)}='{record.GetValue(i)}'"); ////Trace.WriteLine($"Getting data from record {string.Join(",", recordItems)}"); #endif poco = (T)basePocoDelegate.MappingDelegate.DynamicInvoke(record); #if DEBUG } catch (TargetInvocationException ex) { throw new OperationException(basePocoDelegate, $"Error creating a POCO for type {typeof(T)}: {ex.Message}", ex); } #endif return(poco); }
/// <summary> /// Fills the return list with POCOs hydrated from the reader. /// </summary> /// <param name="reader"> /// The reader to read. /// </param> /// <param name="entityDefinition"> /// The entity definition for the POCOs. /// </param> /// <exception cref="OperationException"> /// The <see cref="FlatPocoFactory"/> did not return a delegate of the expected type. /// </exception> private T FillReturnList(IDataReader reader, IEntityDefinition entityDefinition) { var pocoDataRequest = new PocoDataRequest(reader, entityDefinition, this.DatabaseContext); var mappingDelegate = FlatPocoFactory.CreateDelegate <T>(pocoDataRequest).MappingDelegate; if (mappingDelegate is Func <IDataReader, T> pocoDelegate) { var poco = pocoDelegate.Invoke(reader); return(poco); } else { throw new OperationException( pocoDataRequest, string.Format(CultureInfo.CurrentCulture, ErrorMessages.DelegateCouldNotBeCreatedWithReader, pocoDataRequest)); } }
/// <summary> /// Gets a related entity POCO from the reader. /// </summary> /// <param name="entityAggregateName"> /// The entity aggregate name. /// </param> /// <param name="dataRequest"> /// The data request. /// </param> /// <param name="reader"> /// The reader. /// </param> /// <param name="entityReference"> /// The entity reference. /// </param> /// <returns> /// The related POCO as an <see cref="object"/>. /// </returns> private object GetRelatedEntity(string entityAggregateName, PocoDataRequest dataRequest, IDataRecord reader, EntityReference entityReference) { var relatedEntityLocation = this.definitionProvider.GetEntityLocation(entityReference); var relatedQualifiedName = string.IsNullOrWhiteSpace(relatedEntityLocation.Alias) ? $"{relatedEntityLocation.Container}.{relatedEntityLocation.Name}" : relatedEntityLocation.Alias; var relatedKey = new Tuple <string, PocoDataRequest>($"{entityAggregateName}:{relatedQualifiedName}", dataRequest); // TODO: Cache attributes with their locations, or build explicitly. ////var relatedAttributes = entityDefinition.ReturnableAttributes.Where(x => x.ReferenceNode?.Value == relatedEntityLocation).ToList(); var relatedAttributes = dataRequest.AttributeDefinitions.Where(x => x.ReferenceNode?.Value == relatedEntityLocation).ToList(); var relatedType = relatedEntityLocation.EntityType; var relatedPocoDelegate = PocoFactories.GetOrAdd( relatedKey, key => new Lazy <PocoDelegateInfo>(() => FlatPocoFactory.CreateDelegate(dataRequest, relatedType, relatedAttributes))) .Value; object relatedEntity; #if DEBUG try { #endif relatedEntity = relatedPocoDelegate.MappingDelegate.DynamicInvoke(reader); #if DEBUG } catch (TargetInvocationException ex) { throw new OperationException(relatedPocoDelegate, $"Error creating a POCO for type {relatedType}: {ex.Message}", ex); } #endif return(relatedEntity); }