<commit_before>﻿namespace StraightSql
{
	using Npgsql;
	using System;
	using System.Collections.Generic;
	using System.Data;
	using System.Threading.Tasks;

	public class QueryDispatcher
		: IQueryDispatcher
	{
		private readonly ICommandPreparer commandPreparer;
		private readonly IConnectionFactory connectionFactory;

		public QueryDispatcher(ICommandPreparer commandPreparer, IConnectionFactory connectionFactory)
		{
			if (commandPreparer == null)
				throw new ArgumentNullException(nameof(commandPreparer));

			if (connectionFactory == null)
				throw new ArgumentNullException(nameof(connectionFactory));

			this.commandPreparer = commandPreparer;
			this.connectionFactory = connectionFactory;
		}

		public async Task<Boolean> AnyAsync(IQuery query)
		{
			var first = await FirstOrDefaultAsync(query, reader =>
			{
				return new Object();
			});

			return first != null;
		}

		public async Task<Int64> CountAsync(IQuery query)
		{
			return await ExecuteQueryAsync(query, async command =>
			{
				var countResult = await command.ExecuteScalarAsync();
				var count = (Int64)countResult;

				return count;
			});
		}

		public async Task ExecuteAsync(IQuery query)
		{
			using (var connection = await connectionFactory.CreateAsync())
			{
				using (var command = connection.CreateCommand())
				{
					commandPreparer.Prepare(command, query);

					await command.ExecuteNonQueryAsync();
				}
			}
		}

		public async Task<T> FirstAsync<T>(IQuery query, Func<IRow, T> reader)
		{
			var result = await FirstOrDefaultAsync(query, reader);

			if (result == null)
				throw new InvalidOperationException("The sequence contained no elements.");

			return result;
		}

		public async Task<T> FirstOrDefaultAsync<T>(IQuery query, Func<IRow, T> reader)
		{
			using (var connection = await connectionFactory.CreateAsync())
			{
				using (var command = connection.CreateCommand())
				{
					commandPreparer.Prepare(command, query);

					var dataReader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow);

					if (!await dataReader.ReadAsync())
						return default(T);

					return reader(new Row(dataReader));
				}
			}
		}

		public async Task<IList<T>> ListAsync<T>(IQuery query, Func<IRow, T> readerFunction)
		{
			return await ExecuteQueryAsync(query, async command =>
			{
				var list = new List<T>();
				var dataReader = await command.ExecuteReaderAsync();

				while (await dataReader.ReadAsync() != false)
				{
					list.Add(readerFunction(new Row(dataReader)));
				}

				return list;
			});
		}

		public async Task<T> SingleAsync<T>(IQuery query, Func<IRow, T> reader)
		{
			var result = await SingleOrDefaultAsync(query, reader);

			if (result == null)
				throw new InvalidOperationException("The sequence did not contain exactly one element.");<commit_msg>Use consistent syntax with ExecuteQueryAsync().<commit_after>﻿namespace StraightSql
{
	using Npgsql;
	using System;
	using System.Collections.Generic;
	using System.Data;
	using System.Threading.Tasks;

	public class QueryDispatcher
		: IQueryDispatcher
	{
		private readonly ICommandPreparer commandPreparer;
		private readonly IConnectionFactory connectionFactory;

		public QueryDispatcher(ICommandPreparer commandPreparer, IConnectionFactory connectionFactory)
		{
			if (commandPreparer == null)
				throw new ArgumentNullException(nameof(commandPreparer));

			if (connectionFactory == null)
				throw new ArgumentNullException(nameof(connectionFactory));

			this.commandPreparer = commandPreparer;
			this.connectionFactory = connectionFactory;
		}

		public async Task<Boolean> AnyAsync(IQuery query)
		{
			var first = await FirstOrDefaultAsync(query, reader =>
			{
				return new Object();
			});

			return first != null;
		}

		public async Task<Int64> CountAsync(IQuery query)
		{
			return await ExecuteQueryAsync(query, async command =>
			{
				var countResult = await command.ExecuteScalarAsync();
				var count = (Int64)countResult;

				return count;
			});
		}

		public async Task ExecuteAsync(IQuery query)
		{
			await ExecuteQueryAsync(query, async command =>
			{
				await command.ExecuteNonQueryAsync();

				return 0;
			});
		}

		public async Task<T> FirstAsync<T>(IQuery query, Func<IRow, T> reader)
		{
			var result = await FirstOrDefaultAsync(query, reader);

			if (result == null)
				throw new InvalidOperationException("The sequence contained no elements.");

			return result;
		}

		public async Task<T> FirstOrDefaultAsync<T>(IQuery query, Func<IRow, T> reader)
		{
			return await ExecuteQueryAsync(query, async command =>
			{
				var dataReader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow);

				if (!await dataReader.ReadAsync())
					return default(T);

				return reader(new Row(dataReader));
			});
		}

		public async Task<IList<T>> ListAsync<T>(IQuery query, Func<IRow, T> readerFunction)
		{
			return await ExecuteQueryAsync(query, async command =>
			{
				var list = new List<T>();
				var dataReader = await command.ExecuteReaderAsync();

				while (await dataReader.ReadAsync() != false)
				{
					list.Add(readerFunction(new Row(dataReader)));
				}

				return list;
			});
		}

		public async Task<T> SingleAsync<T>(IQuery query, Func<IRow, T> reader)
		{
			var result = await SingleOrDefaultAsync(query, reader);

			if (result == null)
				throw new InvalidOperationException("The sequence did not contain exactly one element.");
{'fraction_non_alphanumeric': 0.09924368197749493, 'fraction_numerical': 0.0016602102933038186, 'mean_word_length': 4.034354688950789, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4104283', 'n_tokens_mistral': 1917, 'n_tokens_neox': 1545, 'n_words': 410}