Beispiel #1
0
        /// <summary>
        /// Takes a <see cref="IResolveFieldContext"/> and returns a hydrated object with the data.
        /// </summary>
        /// <param name="context">The <see cref="IResolveFieldContext"/>.</param>
        /// <param name="databaseCall">A <see cref="DatabaseCallDelegate"/> that is passed the compiled SQL and calls the database and returns a <see cref="IDataReader"/>.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
        /// <returns>The correctly nested data from the database.</returns>
        /// <exception cref="ArgumentNullException">If <c>context</c> or <c>databaseCall</c> is null.</exception>
        public async Task <object?> ExecuteAsync(IResolveFieldContext context, DatabaseCallDelegate databaseCall,
                                                 CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (databaseCall == null)
            {
                throw new ArgumentNullException(nameof(databaseCall));
            }

            var sqlAst    = _converter.Convert(context);
            var sqlResult = _compiler.Compile(sqlAst, context);

            var data = new List <Dictionary <string, object?> >();

            using (var reader = await databaseCall(sqlResult.Sql, sqlResult.Parameters).ConfigureAwait(false))
            {
                while (await reader.ReadAsync(cancellationToken))
                {
                    var item = new Dictionary <string, object?>();

                    for (var i = 0; i < reader.FieldCount; ++i)
                    {
                        var value = await reader.IsDBNullAsync(i, cancellationToken)
                            ? null
                            : await reader.GetFieldValueAsync <object>(i, cancellationToken);

                        item[reader.GetName(i)] = value;
                    }

                    data.Add(item);
                }
            }

            var objectShape = _objectShaper.DefineObjectShape(sqlAst);

#pragma warning disable 8620
            var nested = _hydrator.Nest(data, objectShape);
            var result = _arrayToConnectionConverter.Convert(nested, sqlAst, context);
#pragma warning restore 8620

            if (result == null)
            {
                return(null);
            }

            await _batchPlanner.NextBatch(sqlAst, result, databaseCall, context, cancellationToken).ConfigureAwait(false);

            return(result);
        }