private static IList <T1> AutoQuery <T1>(IDbConnection connection, IList <Type> types, string[] tableAliases, string whereClauseExpression, object parameters, int desiredNumberOfResults, int?offsetInResults, string orderByClauseExpression) { var map = new TypePropertyMap(SimpleSaveExtensions.MetadataCache, types); var query = new QueryBuilder().BuildQuery(map, tableAliases, whereClauseExpression, parameters, desiredNumberOfResults, offsetInResults, orderByClauseExpression); return(QueryInternal <T1>(connection, types, parameters, query, map)); }
public static IList <T1> CustomQuery <T1>( this IDbConnection connection, Type [] additionalTypes, string completeParameterisedSqlQuery, object parameters, string splitOn = null) { var types = BuildAndCheckTypeList <T1>(additionalTypes); var map = new TypePropertyMap(SimpleSaveExtensions.MetadataCache, types); return(QueryInternal <T1>( connection, types, parameters, new Query { Sql = completeParameterisedSqlQuery, SplitOn = splitOn }, map)); }
private static IList <T1> QueryInternal <T1>(IDbConnection connection, IList <Type> types, object parameters, IQuery query, TypePropertyMap map) { var alreadyEncounteredDictionaries = CreateAlreadyEncounteredDictionaries(types.Count); var alreadyEncounteredCollectionValues = new Dictionary <object, HashSet <object> >(); try { var results = new List <T1>(); var rowCount = 0; QueryExecutionLogger.Executing(query, parameters); long startTime = DateTime.Now.Ticks, timeToFirstResult = -1; connection.Query( query.Sql, types.ToArray(), objects => { ++rowCount; if (timeToFirstResult == -1) { timeToFirstResult = (DateTime.Now.Ticks - startTime) / TimeSpan.TicksPerMillisecond; } for (int index = 0, size = objects.Length; index < size; ++index) { var current = objects[index]; if (current == null) { continue; } var alreadyEncountered = alreadyEncounteredDictionaries[index]; var entry = map[index]; var metadata = entry.Metadata; var primaryKey = metadata.GetPrimaryKeyValueAsObject(current); if (alreadyEncountered.Contains(primaryKey)) { current = alreadyEncountered[primaryKey]; } else { alreadyEncountered[primaryKey] = current; if (index == 0) { results.Add((T1)current); } } if (index > 0) { var targetEntry = map.GetEntryWithMatchingPropertyPreceding(index, entry.Type); var propertyMetadata = targetEntry.GetPropertyMetadataFor(entry.Type); var targetObject = objects[targetEntry.Index]; var targetsAlreadyEncountered = alreadyEncounteredDictionaries[targetEntry.Index]; var targetPrimaryKey = targetEntry.Metadata.GetPrimaryKeyValueAsObject(targetObject); if (targetsAlreadyEncountered.Contains(targetPrimaryKey)) { targetObject = targetsAlreadyEncountered[targetPrimaryKey]; } else { targetsAlreadyEncountered[targetPrimaryKey] = targetObject; } if (propertyMetadata.Prop.PropertyType == entry.Type) { propertyMetadata.Prop.SetValue(targetObject, current); } else if (propertyMetadata.IsEnumerable) { MethodInfo addMethod; var collection = propertyMetadata.Prop.GetValue(targetObject); if (null == collection) { var genericArgs = propertyMetadata.Prop.PropertyType.GenericTypeArguments; if (genericArgs != null && genericArgs.Length > 0) { var genericList = typeof(List <>); var instantiable = genericList.MakeGenericType(genericArgs); collection = Activator.CreateInstance(instantiable); addMethod = instantiable.GetMethod("Add"); } else { collection = new ArrayList(); addMethod = typeof(ArrayList).GetMethod("Add"); } propertyMetadata.Prop.SetValue(targetObject, collection); } else { addMethod = collection.GetType().GetMethod("Add"); } if (addMethod == null) { throw new InvalidOperationException( string.Format( "The type '{0}' of property '{1}' on '{2}' does not implement an " + "Add(object) method so objects of type '{3}' cannot be added to it.", propertyMetadata.Prop.PropertyType.FullName, propertyMetadata.Prop.Name, targetEntry.Metadata.DtoType.FullName, metadata.DtoType.FullName)); } HashSet <object> seenBefore; alreadyEncounteredCollectionValues.TryGetValue(collection, out seenBefore); if (seenBefore == null) { seenBefore = new HashSet <object>(); alreadyEncounteredCollectionValues[collection] = seenBefore; } if (!seenBefore.Contains(current)) { addMethod.Invoke(collection, new[] { current }); seenBefore.Add(current); } } else { throw new InvalidOperationException( string.Format( "The property '{0}' on '{1}' is of type '{2}', which does not match " + "the type of value to be set, which is a '{3}', nor is it a list to " + "which the '{3}' can be added", propertyMetadata.Prop.Name, targetEntry.Metadata.DtoType.FullName, propertyMetadata.Prop.PropertyType.FullName, metadata.DtoType.FullName)); } } } return(true); }, splitOn: query.SplitOn, param: parameters); QueryExecutionLogger.Executed(query, parameters, rowCount, startTime, timeToFirstResult); return(results); } catch (SqlException se) { throw new AnnotatedSqlException(se, query.Sql, query.SplitOn, parameters); } }