コード例 #1
0
        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));
        }
コード例 #2
0
        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));
        }
コード例 #3
0
        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);
            }
        }