/// <summary> /// Return an enumerable which uses lazy loading of each row. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="unitOfWork">UnitOfWork to invoke <c>ExecuteReaderAsync()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="ownsConnection"> /// <c>true</c> if the connection should be disposed together with the command/datareader. See /// remarks. /// </param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters"> /// Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or /// a value array /// </param> /// <returns>Lazy loaded enumerator</returns> /// <remarks> /// <para> /// For more information about the "query" and "parameters" arguments, see /// <see cref="CommandExtensions.ApplyQuerySql{TEntity}" />. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// // All these examples are valid: /// <![CDATA[ /// var users = await unitOfWork.ToEnumerable<User>(true, "Age < 10"); /// var users = await unitOfWork.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = 37"); /// var users = await unitOfWork.ToEnumerable<User>(true, "FirstName = @name", new { name = user.FirstName }); /// var users = await unitOfWork.ToEnumerable<User>(true, "FirstName = @1 AND Age < @2", 'A%', 35); /// var users = await unitOfWork.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = @age LIMIT 1, 10", new { age = submittedAge }); /// var users = await unitOfWork.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = @1 LIMIT 1, 10", user.FirstName); /// ]]> /// </code> /// </example> public static async Task <IEnumerable <TEntity> > ToEnumerableAsync <TEntity>(this IAdoNetUnitOfWork unitOfWork, bool ownsConnection, string query, params object[] parameters) { if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); } if (query == null) { throw new ArgumentNullException("query"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); //no using since AdoNetEntityEnumerable will own it. var cmd = unitOfWork.CreateDbCommand(); try { cmd.ApplyQuerySql(mapping, query, parameters); var reader = await cmd.ExecuteReaderAsync(); return(new AdoNetEntityEnumerable <TEntity>(cmd, reader, mapping, ownsConnection)); } catch (Exception e) { throw cmd.CreateDataException(e); } }
/// <summary> /// Fetches the first row if found. /// </summary> /// <typeparam name="TEntity">Type of entity to load, must have an mapper registered in <see cref="EntityMappingProvider"/>.</typeparam> /// <param name="connection">Connection to invoke <c>ExecuteReader()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters">Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or a value array</param> /// <returns> /// Entity if found; otherwise <c>null</c>. /// </returns> /// <remarks> /// <para>Use this method when an entity is expected to be returned.</para> /// <para>Uses <see cref="EntityMappingProvider"/> to find the correct <c><![CDATA[ICrudEntityMapper<TEntity>]]></c></para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public User GetUser(int userId) /// { /// return _connection.FirstOrDefault<User>("WHERE age < @Age", new { Age = minAge }); /// } /// ]]> /// </code> /// </example> public static TEntity FirstOrDefault <TEntity>(this IDbConnection connection, string query, params object[] parameters) { if (connection == null) { throw new ArgumentNullException("connection"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); using (var cmd = connection.CreateDbCommand()) { if (!query.Trim().StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) { var crudMapper = mapping as ICrudEntityMapper <TEntity>; if (crudMapper == null) { throw new MappingException(typeof(TEntity), "Mapping must be of type ICrudEntityMapper<T>."); } cmd.CommandText = $"SELECT * FROM {crudMapper.TableName} WHERE "; } else { cmd.CommandText = query; } cmd.ApplyQuerySql(mapping, query, parameters); return(cmd.FirstOrDefault <TEntity>()); } }
/// <summary> /// Return an enumerable which uses lazy loading of each row. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="cmd">Command to invoke <c>ExecuteReaderAsync()</c> on.</param> /// <param name="ownsConnection"> /// <c>true</c> if the connection should be disposed together with the command/datareader. See /// remarks. /// </param> /// <param name="mapper">Mapper used to convert rows to entities</param> /// <returns>Lazy loaded enumerator</returns> /// <remarks> /// <para> /// The command is executed asynchronously. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para> /// Requires that a <c><![CDATA[IEntityMapper<TEntity>]]></c> is registered in the /// <see cref="EntityMappingProvider" />. /// </para> /// </remarks> public static async Task <IEnumerable <TEntity> > ToEnumerableAsync <TEntity>(this IDbCommand cmd, bool ownsConnection, IEntityMapper <TEntity> mapper) { if (cmd == null) { throw new ArgumentNullException("cmd"); } if (mapper == null) { throw new ArgumentNullException("mapper"); } var command = GetDbCommandFromInterface(cmd); try { var reader = await command.ExecuteReaderAsync(); var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(new AdoNetEntityEnumerable <TEntity>(cmd, reader, mapping, ownsConnection)); } catch (Exception e) { throw command.CreateDataException(e); } }
public static void ApplyQuerySql <TEntity>(this IDbCommand cmd, string sql, params object[] parameters) { var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); ApplyQuerySql(cmd, mapping, sql, parameters); }
/// <summary> /// Fetches the first row and maps it as an entity (if found). /// </summary> /// <typeparam name="TEntity">Type of entity to use, must have an mapper registered in <see cref="EntityMappingProvider"/>.</typeparam> /// <param name="cmd">Command to invoke <c>ExecuteReader()</c> on.</param> /// <returns>Entity if found; otherwise <c>null</c>.</returns> /// <example> /// <code> /// <![CDATA[ /// public void FindUser(string id) /// { /// using (var command = connection.CreateCommand()) /// { /// cmd.CommandText = "SELECT * FROM Users WHERE Id = @id"; /// cmd.AddParameter("id", userId); /// return cmd.FirstOrDefault<User>(); /// } /// } /// ]]> /// </code> /// </example> public static TEntity FirstOrDefault <TEntity>(this IDbCommand cmd) { if (cmd == null) { throw new ArgumentNullException("cmd"); } try { using (var reader = cmd.ExecuteReader()) { if (!reader.Read()) { return(default(TEntity)); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); var entity = (TEntity)mapping.Create(reader); mapping.Map(reader, entity); return(entity); } } catch (Exception e) { throw cmd.CreateDataException(e); } }
/// <summary> /// Generate a complete list before returning. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="connection">Connection to invoke <c>ExecuteReader()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters">Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or a value array</param> /// <returns>A list.</returns> /// <remarks> /// <para> /// For more information about the "query" and "parameters" arguments, see <see cref="CommandExtensions.ApplyQuerySql{TEntity}"/>. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[ICrudEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// // All these examples are valid: /// <![CDATA[ /// var users = connection.ToList<User>("Age < 10"); /// var users = connection.ToList<User>("SELECT * FROM Users WHERE Age = 37"); /// var users = connection.ToList<User>("FirstName = @name", new { name = user.FirstName }); /// var users = connection.ToList<User>("FirstName = @1 AND Age < @2", 'A%', 35); /// var users = connection.ToList<User>("SELECT * FROM Users WHERE Age = @age LIMIT 1, 10", new { age = submittedAge }); /// var users = connection.ToList<User>("SELECT * FROM Users WHERE Age = @1 LIMIT 1, 10", user.FirstName); /// ]]> /// </code> /// </example> public static IList <TEntity> ToList <TEntity>(this IDbConnection connection, string query, params object[] parameters) { if (connection == null) { throw new ArgumentNullException("connection"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(ToList(connection, mapping, query, parameters)); }
/// <summary> /// Generate a complete list before returning. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="cmd">Command to invoke <c>ExecuteReaderAsync()</c> on.</param> /// <returns>A list which is generated asynchronously.</returns> /// <remarks> /// <para> /// Uses the <see cref="EntityMappingProvider" /> to find the correct base mapper. /// </para> /// <para> /// Make sure that you <c>await</c> the method, as nothing the reader is not disposed directly if you don't. /// </para> /// </remarks> public static async Task <IList <TEntity> > ToListAsync <TEntity>(this IDbCommand cmd) { if (cmd == null) { throw new ArgumentNullException("cmd"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(await ToListAsync(cmd, mapping)); }
/// <summary> /// Fetches the first row if found. /// </summary> /// <param name="cmd">Command to invoke <c>ExecuteReaderAsync()</c> on.</param> /// <returns> /// Entity if found; otherwise <c>null</c>. /// </returns> /// <remarks> /// <para>Use this method when an entity is expected to be returned.</para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public async Task<User> GetUser(int userId) /// { /// using (var command = connection.CreateCommand()) /// { /// cmd.CommandText = "SELECT * FROM Users WHERE Id = @id"; /// cmd.AddParameter("id", userId); /// return await cmd.FirstOrDefaultAsync<User>(); /// } /// } /// ]]> /// </code> /// </example> public static Task <TEntity> FirstOrDefaultAsync <TEntity>(this IDbCommand cmd) { if (cmd == null) { throw new ArgumentNullException("cmd"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(FirstOrDefaultAsync(cmd, mapping)); }
/// <summary> /// Return an enumerable which uses lazy loading of each row. /// </summary> /// <typeparam name="TEntity">Type of entity to use, must have an mapper registered in <see cref="EntityMappingProvider"/>.</typeparam> /// <param name="cmd">Command to invoke <c>ExecuteReader()</c> on.</param> /// <param name="ownsConnection"> /// <c>true</c> if the connection should be disposed together with the command/datareader. See /// remarks. /// </param> /// <returns>Lazy loaded enumerator</returns> /// <remarks> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para> /// As the returned item is a custom lazy loaded enumerable it's quite fast as nothing is mapped if you do like: /// </para> /// <example> /// <code> /// <![CDATA[ /// using (var cmd = connection.CreateCommand()) /// { /// cmd.CommandText = "SELECT * FROM Users"; /// var pagedUsers = cmd.ToEnumerable<User>().Skip(1000).Take(50).ToList(); /// } /// ]]> /// </code> /// </example> /// <para> /// Do note that it will still read all rows and is therefore slower than paging in the SQL server. It will however /// use a lot less /// allocations than building a complete list first. /// </para> /// <para> /// If the result returnd from the query is all records that you want it's probably more effecient to use /// <see cref="ToList{TEntity}(IDbCommand)" />. /// </para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public TimeSpan CalculateWorkHours() /// { /// int minutes = 0; /// using (var command = connection.CreateCommand()) /// { /// cmd.CommandText = "SELECT * FROM Users WHERE Id = @id"; /// cmd.AddParameter("id", userId); /// /// // can contain a large amount of rows without consuming memory /// using (var incidents = cmd.ToEnumerable<Incident>()) /// { /// foreach (var incident in incidents) /// { /// if (!incident.IsStarted) /// continue; /// /// var spentTime = incident.ReportedTime.Sum(x => x.TotalSpentTime); /// minutes += spentTime; /// } /// } /// } /// /// return TimeSpan.FromMinutes(minutes); /// } /// ]]> /// </code> /// </example> public static IEnumerable <TEntity> ToEnumerable <TEntity>(this IDbCommand cmd, bool ownsConnection) { if (cmd == null) { throw new ArgumentNullException("cmd"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(ToEnumerable(cmd, ownsConnection, mapping)); }
/// <summary> /// Return an enumerable which uses lazy loading of each row. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="cmd">Command to invoke <c>ExecuteReaderAsync()</c> on.</param> /// <param name="ownsConnection"> /// <c>true</c> if the connection should be disposed together with the command/datareader. See /// remarks. /// </param> /// <returns>Lazy loaded enumerator</returns> /// <remarks> /// <para> /// The command is executed asynchronously. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c>.</para> /// </remarks> public static async Task <IEnumerable <TEntity> > ToEnumerableAsync <TEntity>(this DbCommand cmd, bool ownsConnection) { if (cmd == null) { throw new ArgumentNullException("cmd"); } var reader = await cmd.ExecuteReaderAsync(); var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(new AdoNetEntityEnumerable <TEntity>(cmd, reader, mapping, ownsConnection)); }
/// <summary> /// Get an entity. /// </summary> /// <typeparam name="TEntity">Type of entity to load, must have an mapper registered in <see cref="EntityMappingProvider"/>.</typeparam> /// <param name="connection">connection to load entity from</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters">Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or a value array</param> /// <returns>Found entity</returns> /// <remarks> /// <para>Uses <see cref="EntityMappingProvider"/> to find the correct <c><![CDATA[ICrudEntityMapper<TEntity>]]></c></para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public User GetUser(int userId) /// { /// return _connection.First<User>("WHERE id = @id", new { id = UserId }); /// } /// ]]> /// </code> /// <para> /// Which will translate into: /// </para> /// <code> /// command.CommandText = "SELECT * FROM Users WHERE id = @id"; /// var p = command.CreateParameter(); /// p.Name = "id"; /// p.Value = userId; /// command.Parameters.Add(p); /// </code> /// </example> /// <exception cref="EntityNotFoundException">Failed to find an entity mathing the query</exception> public static TEntity First <TEntity>(this IDbConnection connection, string query, params object[] parameters) { if (connection == null) { throw new ArgumentNullException("connection"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); using (var cmd = connection.CreateDbCommand()) { cmd.ApplyQuerySql(mapping, query, parameters); return(cmd.First(mapping)); } }
/// <summary> /// Get an entity. /// </summary> /// <typeparam name="TEntity">Type of entity to load, must have an mapper registered in <see cref="EntityMappingProvider"/>.</typeparam> /// <param name="unitOfWork">Unit of work to invoke <c>ExecuteReader()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters">Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or a value array</param> /// <returns>Found entity</returns> /// <remarks> /// <para>Uses <see cref="EntityMappingProvider"/> to find the correct <c><![CDATA[ICrudEntityMapper<TEntity>]]></c></para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public User GetUser(int userId) /// { /// return unitOfWork.First<User>("WHERE id = @id", new { id = UserId }); /// } /// ]]> /// </code> /// <para> /// Which will translate into: /// </para> /// <code> /// command.CommandText = "SELECT * FROM Users WHERE id = @id"; /// var p = command.CreateParameter(); /// p.Name = "id"; /// p.Value = userId; /// command.Parameters.Add(p); /// </code> /// </example> /// <exception cref="EntityNotFoundException">Failed to find an entity mathing the query</exception> public static TEntity First <TEntity>(this IAdoNetUnitOfWork unitOfWork, string query, params object[] parameters) { if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); using (var cmd = unitOfWork.CreateDbCommand()) { cmd.ApplyQuerySql(mapping, query, parameters); return(cmd.First(mapping)); } }
/// <summary> /// Generate a complete list before returning. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="unitOfWork">Unit of work to invoke <c>ExecuteReaderAsync()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="query">Query or short query (<c><![CDATA["projectId = @id AND dateCreated < @minDate"]]></c>)</param> /// <param name="parameters"> /// Anonymous object (<c>new { id = dto.ProjectId, @minDate = dto.MinDate }</c>), a dictionary or /// a value array /// </param> /// <returns>A list which is generated asynchronously.</returns> /// <remarks> /// <para> /// For more information about the "query" and "parameters" arguments, see /// <see cref="CommandExtensions.ApplyQuerySql{TEntity}" />. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[ICrudEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// // All these examples are valid: /// <![CDATA[ /// var users = await unitOfWork.ToListAsync<User>("Age < 10"); /// var users = await unitOfWork.ToListAsync<User>("SELECT * FROM Users WHERE Age = 37"); /// var users = await unitOfWork.ToListAsync<User>("FirstName = @name", new { name = user.FirstName }); /// var users = await unitOfWork.ToListAsync<User>("FirstName = @1 AND Age < @2", 'A%', 35); /// var users = await unitOfWork.ToListAsync<User>("SELECT * FROM Users WHERE Age = @age LIMIT 1, 10", new { age = submittedAge }); /// var users = await unitOfWork.ToListAsync<User>("SELECT * FROM Users WHERE Age = @1 LIMIT 1, 10", user.FirstName); /// ]]> /// </code> /// </example> public static async Task <List <TEntity> > ToListAsync <TEntity>(this IAdoNetUnitOfWork unitOfWork, string query, params object[] parameters) { if (unitOfWork == null) { throw new ArgumentNullException("unitOfWork"); } if (query == null) { throw new ArgumentNullException("query"); } if (parameters == null) { throw new ArgumentNullException("parameters"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(await ToListAsync(unitOfWork, mapping, query, parameters)); }
/// <summary> /// Return an enumerable which uses lazy loading of each row. /// </summary> /// <typeparam name="TEntity">Type of entity to map</typeparam> /// <param name="connection">Connection to invoke <c>ExecuteReader()</c> on (through a created <c>DbCommand</c>).</param> /// <param name="ownsConnection"> /// <c>true</c> if the connection should be disposed together with the command/datareader. See /// remarks. /// </param> /// <param name="query">Query or short query (<c>"id = @1"</c>)</param> /// <param name="parameters"></param> /// <returns>Lazy loaded enumerator</returns> /// <remarks> /// <para> /// For more information about the "query" and "parameters" arguments, see <see cref="CommandExtensions.ApplyQuerySql{TEntity}"/>. /// </para> /// <para> /// The returned enumerator will not map each row until it's requested. To be able to do that the /// connection/command/datareader is /// kept open until the enumerator is disposed. Hence it's important that you make sure that the enumerator is /// disposed when you are /// done with it. /// </para> /// <para>Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c>.</para> /// </remarks> /// <example> /// <code> /// // All these examples are valid: /// <![CDATA[ /// var users = connection.ToEnumerable<User>(true, "Age < 10"); /// var users = connection.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = 37"); /// var users = connection.ToEnumerable<User>(true, "FirstName = @name", new { name = user.FirstName }); /// var users = connection.ToEnumerable<User>(true, "FirstName = @1 AND Age < @2", 'A%', 35); /// var users = connection.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = @age LIMIT 1, 10", new { age = submittedAge }); /// var users = connection.ToEnumerable<User>(true, "SELECT * FROM Users WHERE Age = @1 LIMIT 1, 10", user.FirstName); /// ]]> /// </code> /// </example> public static IEnumerable <TEntity> ToEnumerable <TEntity>(this IDbConnection connection, bool ownsConnection, string query, params object[] parameters) { if (connection == null) { throw new ArgumentNullException("connection"); } var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); var cmd = connection.CreateDbCommand(); try { cmd.ApplyQuerySql(mapping, query, parameters); var reader = cmd.ExecuteReader(); return(new AdoNetEntityEnumerable <TEntity>(cmd, reader, mapping, ownsConnection)); } catch (Exception e) { throw cmd.CreateDataException(e); } }
/// <summary> /// Fetches the first found entity asynchronously /// </summary> /// <param name="cmd">Command to invoke <c>ExecuteReaderAsync()</c> on.</param> /// <returns> /// entity /// </returns> /// <exception cref="EntityNotFoundException">Failed to find specified entity.</exception> /// <remarks> /// <para>Use this method when an entity is expected to be returned.</para> /// <para> /// Uses <see cref="EntityMappingProvider" /> to find the correct <c><![CDATA[IEntityMapper<TEntity>]]></c> /// </para> /// </remarks> /// <example> /// <code> /// <![CDATA[ /// public async Task<User> GetUser(int userId) /// { /// using (var command = connection.CreateCommand()) /// { /// cmd.CommandText = "SELECT * FROM Users WHERE Id = @id"; /// cmd.AddParameter("id", userId); /// return await cmd.FirstAsync<User>(); /// } /// } /// ]]> /// </code> /// </example> public static Task <TEntity> FirstAsync <TEntity>(this IDbCommand cmd) { var mapping = EntityMappingProvider.GetBaseMapper <TEntity>(); return(FirstAsync(cmd, mapping)); }