Skip to content

Commit 3922b96

Browse files
Update version and enhance SqlCommandExtensions methods
- Bump `VersionPrefix` from `9.0.2` to `9.0.3`. - Add `ExecuteReader<T>` and `ExecuteReaderAsync<T>` methods to `SqlCommandExtensions` for improved data reading with transformation functions. - Implement null checks for parameters in the new methods. - Enhance documentation for new methods and clarify parameter types. - Include conditional compilation for compatibility across .NET versions.
1 parent 233e19d commit 3922b96

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

Source/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<RootNamespace>Open.Database.Extensions</RootNamespace>
55

6-
<VersionPrefix>9.0.2</VersionPrefix>
6+
<VersionPrefix>9.0.3</VersionPrefix>
77
<VersionSuffix Condition="'$(Configuration)' == 'Debug'">debug</VersionSuffix>
88

99
<TargetFrameworks>netstandard2.0; netstandard2.1; net8.0; net9.0;</TargetFrameworks>

Source/MSSqlClient/Extensions/Command.ExecuteReader.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ public static void ExecuteReader(this SqlCommand command, Action<SqlDataReader>
4444
handler(reader);
4545
}
4646

47+
/// <param name="command">The <see cref="SqlCommand"/> to generate a reader from.</param>
48+
/// <param name="transform">The transform function for each <see cref="SqlDataReader"/>.</param>
49+
/// <param name="behavior">The behavior to use with the data reader.</param>
50+
/// <inheritdoc cref="CommandExtensions.ExecuteReader{T}(IDbCommand, Func{IDataReader, T}, CommandBehavior)"/>
51+
public static T ExecuteReader<T>(this SqlCommand command, Func<SqlDataReader, T> transform, CommandBehavior behavior = CommandBehavior.Default)
52+
{
53+
if (command is null) throw new ArgumentNullException(nameof(command));
54+
if (transform is null) throw new ArgumentNullException(nameof(transform));
55+
Contract.EndContractBlock();
56+
57+
ConnectionState state = command.EnsureOpen();
58+
if (state == ConnectionState.Closed) behavior |= CommandBehavior.CloseConnection;
59+
using SqlDataReader reader = command.ExecuteReader(behavior);
60+
return transform(reader);
61+
}
62+
4763
/// <param name="command">The <see cref="SqlCommand"/> to generate a reader from.</param>
4864
/// <param name="handler">The handler function for the <see cref="SqlDataReader"/>.</param>
4965
/// <param name="behavior">The behavior to use with the data reader.</param>
@@ -92,7 +108,7 @@ public static async ValueTask ExecuteReaderAsync(this SqlCommand command,
92108
}
93109

94110
/// <param name="command">The <see cref="DbCommand"/> to generate a reader from.</param>
95-
/// <param name="transform">The transform function for each <see cref="IDataRecord"/>.</param>
111+
/// <param name="transform">The transform function the <see cref="DbDataReader"/>.</param>
96112
/// <param name="behavior">The behavior to use with the data reader.</param>
97113
/// <param name="cancellationToken">The cancellation token.</param>
98114
/// <inheritdoc cref="CommandExtensions.ExecuteReaderAsync{T}(DbCommand, Func{DbDataReader, ValueTask{T}}, CommandBehavior, CancellationToken)"/>/>
@@ -117,4 +133,27 @@ public static async ValueTask<T> ExecuteReaderAsync<T>(this SqlCommand command,
117133
using SqlDataReader reader = await command.ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false);
118134
return transform(reader);
119135
}
136+
137+
/// <inheritdoc cref="ExecuteReaderAsync{T}(SqlCommand, Func{SqlDataReader, T}, CommandBehavior, CancellationToken)"/>
138+
public static async ValueTask<T> ExecuteReaderAsync<T>(this SqlCommand command,
139+
Func<SqlDataReader, ValueTask<T>> transform,
140+
CommandBehavior behavior = CommandBehavior.Default,
141+
CancellationToken cancellationToken = default)
142+
{
143+
if (command is null) throw new ArgumentNullException(nameof(command));
144+
if (transform is null) throw new ArgumentNullException(nameof(transform));
145+
Contract.EndContractBlock();
146+
147+
ConnectionState state = await command
148+
.EnsureOpenAsync(cancellationToken)
149+
.ConfigureAwait(false);
150+
151+
if (state == ConnectionState.Closed) behavior |= CommandBehavior.CloseConnection;
152+
#if NET472
153+
#else
154+
await
155+
#endif
156+
using SqlDataReader reader = await command.ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false);
157+
return await transform(reader);
158+
}
120159
}

Source/SqlClient/Extensions/Command.ExecuteReader.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@ public static void ExecuteReader(this SqlCommand command, Action<SqlDataReader>
4444
handler(reader);
4545
}
4646

47+
/// <param name="command">The <see cref="SqlCommand"/> to generate a reader from.</param>
48+
/// <param name="transform">The transform function for each <see cref="SqlDataReader"/>.</param>
49+
/// <param name="behavior">The behavior to use with the data reader.</param>
50+
/// <inheritdoc cref="CommandExtensions.ExecuteReader{T}(IDbCommand, Func{IDataReader, T}, CommandBehavior)"/>
51+
public static T ExecuteReader<T>(this SqlCommand command, Func<SqlDataReader, T> transform, CommandBehavior behavior = CommandBehavior.Default)
52+
{
53+
if (command is null) throw new ArgumentNullException(nameof(command));
54+
if (transform is null) throw new ArgumentNullException(nameof(transform));
55+
Contract.EndContractBlock();
56+
57+
ConnectionState state = command.EnsureOpen();
58+
if (state == ConnectionState.Closed) behavior |= CommandBehavior.CloseConnection;
59+
using SqlDataReader reader = command.ExecuteReader(behavior);
60+
return transform(reader);
61+
}
62+
4763
/// <param name="command">The <see cref="SqlCommand"/> to generate a reader from.</param>
4864
/// <param name="handler">The handler function for the <see cref="SqlDataReader"/>.</param>
4965
/// <param name="behavior">The behavior to use with the data reader.</param>
@@ -92,7 +108,7 @@ public static async ValueTask ExecuteReaderAsync(this SqlCommand command,
92108
}
93109

94110
/// <param name="command">The <see cref="DbCommand"/> to generate a reader from.</param>
95-
/// <param name="transform">The transform function for each <see cref="IDataRecord"/>.</param>
111+
/// <param name="transform">The transform function the <see cref="DbDataReader"/>.</param>
96112
/// <param name="behavior">The behavior to use with the data reader.</param>
97113
/// <param name="cancellationToken">The cancellation token.</param>
98114
/// <inheritdoc cref="CommandExtensions.ExecuteReaderAsync{T}(DbCommand, Func{DbDataReader, ValueTask{T}}, CommandBehavior, CancellationToken)"/>/>
@@ -117,4 +133,27 @@ public static async ValueTask<T> ExecuteReaderAsync<T>(this SqlCommand command,
117133
using SqlDataReader reader = await command.ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false);
118134
return transform(reader);
119135
}
136+
137+
/// <inheritdoc cref="ExecuteReaderAsync{T}(SqlCommand, Func{SqlDataReader, T}, CommandBehavior, CancellationToken)"/>
138+
public static async ValueTask<T> ExecuteReaderAsync<T>(this SqlCommand command,
139+
Func<SqlDataReader, ValueTask<T>> transform,
140+
CommandBehavior behavior = CommandBehavior.Default,
141+
CancellationToken cancellationToken = default)
142+
{
143+
if (command is null) throw new ArgumentNullException(nameof(command));
144+
if (transform is null) throw new ArgumentNullException(nameof(transform));
145+
Contract.EndContractBlock();
146+
147+
ConnectionState state = await command
148+
.EnsureOpenAsync(cancellationToken)
149+
.ConfigureAwait(false);
150+
151+
if (state == ConnectionState.Closed) behavior |= CommandBehavior.CloseConnection;
152+
#if NETSTANDARD2_0
153+
#else
154+
await
155+
#endif
156+
using SqlDataReader reader = await command.ExecuteReaderAsync(behavior, cancellationToken).ConfigureAwait(false);
157+
return await transform(reader);
158+
}
120159
}

0 commit comments

Comments
 (0)