Skip to content

Commit 95210cd

Browse files
Enhance async methods and update DBNull handling
- Updated `RetrieveAsync` in `ExpressiveDbCommandBase` to support `IEnumerable<int>` for .NET 8+ while preserving previous behavior. - Modified `AsEnumerable` in `DataReaderExtensions` to accept `IEnumerable<int>` for .NET 8+, with documentation improvements. - Renamed `CopyToWithDbNullAsNull` to `CopyToDBNullAsNull` in `CoreExtensions` for consistency, updating related overloads. - Streamlined `ReplaceDBNullWithNull` to utilize the new `CopyToDBNullAsNull` method. - Added a new overload of `ReplaceDBNullWithNull` for `List<object?>` to handle `DBNull` values directly. - Updated `To<T>` method in `CoreExtensions` to accept `IEnumerable<(string Field, string? Column)>` for .NET 8+, maintaining previous overload for earlier versions.
1 parent c20b29b commit 95210cd

File tree

3 files changed

+69
-14
lines changed

3 files changed

+69
-14
lines changed

Source/Core/ExpressiveDbCommandBase.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,13 @@ public ValueTask<IEnumerable<T0>> FirstOrdinalResultsAsync<T0>()
207207
/// <param name="n">The first ordinal to include in the request to the reader for each record.</param>
208208
/// <param name="others">The remaining ordinals to request from the reader for each record.</param>
209209
/// <returns>The QueryResult that contains all the results and the column mappings.</returns>
210+
#if NET8_0_OR_GREATER
211+
public ValueTask<QueryResultQueue<object[]>> RetrieveAsync(int n, params IEnumerable<int> others)
212+
=> RetrieveAsync(others.Prepend(n));
213+
#else
210214
public ValueTask<QueryResultQueue<object[]>> RetrieveAsync(int n, params int[] others)
211215
=> RetrieveAsync(Concat(n, others));
216+
#endif
212217

213218
/// <summary>
214219
/// Iterates all records within the current result set using an IDataReader and returns the desired results.

Source/Core/Extensions/DataReader.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -273,19 +273,25 @@ internal static IEnumerable<object[]> AsEnumerableInternal(
273273
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, IEnumerable<int> ordinals)
274274
=> AsEnumerableInternal(reader, ordinals, false);
275275

276-
/// <param name="reader">The reader to enumerate.</param>
277-
/// <param name="ordinals">The limited set of ordinals to include. If none are specified, the returned objects will be empty.</param>
278-
/// <param name="arrayPool">The array pool to acquire buffers from.</param>
279-
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
280-
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, IEnumerable<int> ordinals, ArrayPool<object>? arrayPool)
281-
=> AsEnumerableInternal(reader, ordinals, false, arrayPool);
282-
283276
/// <param name="reader">The reader to enumerate.</param>
284277
/// <param name="n">The first ordinal to include in the request to the reader for each record.</param>
285278
/// <param name="others">The remaining ordinals to request from the reader for each record.</param>
286279
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
280+
#if NET8_0_OR_GREATER
281+
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, int n, params IEnumerable<int> others)
282+
=> AsEnumerableInternal(reader, others.Prepend(n), false);
283+
#else
284+
287285
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, int n, params int[] others)
288286
=> AsEnumerable(reader, CoreExtensions.Concat(n, others));
287+
#endif
288+
289+
/// <param name="reader">The reader to enumerate.</param>
290+
/// <param name="ordinals">The limited set of ordinals to include. If none are specified, the returned objects will be empty.</param>
291+
/// <param name="arrayPool">The array pool to acquire buffers from.</param>
292+
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
293+
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, IEnumerable<int> ordinals, ArrayPool<object>? arrayPool)
294+
=> AsEnumerableInternal(reader, ordinals, false, arrayPool);
289295

290296
/// <summary>
291297
/// Provides an enumerable for iterating all the remaining values of the current result set of a data reader.

Source/Core/Extensions/_.cs

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal static IEnumerable<T> Concat<T>(T first, ICollection<T> remaining)
3131
/// to the <paramref name="target"/> span
3232
/// with any <see cref="DBNull"/> values converted to <see langword="null"/>.
3333
/// </summary>
34-
public static Span<object?> CopyToWithDbNullAsNull(this ReadOnlySpan<object?> values, Span<object?> target)
34+
public static Span<object?> CopyToDBNullAsNull(this ReadOnlySpan<object?> values, Span<object?> target)
3535
{
3636
int len = values.Length;
3737
object?[] result = new object?[len];
@@ -41,9 +41,18 @@ internal static IEnumerable<T> Concat<T>(T first, ICollection<T> remaining)
4141
return result;
4242
}
4343

44-
/// <inheritdoc cref="CopyToWithDbNullAsNull(ReadOnlySpan{object?}, Span{object?})"/>
45-
public static Span<object?> CopyToWithDbNullAsNull(this Span<object?> values, Span<object?> target)
46-
=> CopyToWithDbNullAsNull((ReadOnlySpan<object?>)values, target);
44+
/// <inheritdoc cref="CopyToDBNullAsNull(ReadOnlySpan{object?}, Span{object?})"/>
45+
public static Span<object?> CopyToDBNullAsNull(this Span<object?> values, Span<object?> target)
46+
=> CopyToDBNullAsNull((ReadOnlySpan<object?>)values, target);
47+
48+
49+
/// <inheritdoc cref="CopyToDBNullAsNull(ReadOnlySpan{object?}, Span{object?})"/>
50+
public static Span<object?> CopyToDBNullAsNull(this ReadOnlySpan<object?> values, Memory<object?> target)
51+
=> CopyToDBNullAsNull(values, target.Span);
52+
53+
/// <inheritdoc cref="CopyToDBNullAsNull(ReadOnlySpan{object?}, Span{object?})"/>
54+
public static Span<object?> CopyToDBNullAsNull(this Span<object?> values, Memory<object?> target)
55+
=> CopyToDBNullAsNull((ReadOnlySpan<object?>)values, target.Span);
4756

4857
/// <summary>
4958
/// Any <see cref="DBNull"/> values are yielded as null.
@@ -70,7 +79,7 @@ internal static IEnumerable<T> Concat<T>(T first, ICollection<T> remaining)
7079
Contract.EndContractBlock();
7180

7281
object?[] result = new object?[values.Length];
73-
CopyToWithDbNullAsNull(values.AsSpan(), result.AsSpan());
82+
CopyToDBNullAsNull(values.AsSpan(), result.AsSpan());
7483
return result;
7584
}
7685

@@ -81,7 +90,7 @@ internal static IEnumerable<T> Concat<T>(T first, ICollection<T> remaining)
8190
public static object?[] DBNullToNullCopy(this ReadOnlySpan<object?> values)
8291
{
8392
object?[] result = new object?[values.Length];
84-
DBNullToNullCopy(values, result.AsSpan());
93+
CopyToDBNullAsNull(values, result.AsSpan());
8594
return result;
8695
}
8796

@@ -94,7 +103,14 @@ internal static IEnumerable<T> Concat<T>(T first, ICollection<T> remaining)
94103
/// </summary>
95104
/// <param name="values">The source values.</param>
96105
public static Span<object?> ReplaceDBNullWithNull(this Span<object?> values)
97-
=> DBNullToNullCopy(values, values);
106+
=> CopyToDBNullAsNull(values, values);
107+
108+
/// <inheritdoc cref="ReplaceDBNullWithNull(Span{object?})"/>
109+
public static Memory<object?> ReplaceDBNullWithNull(this Memory<object?> values)
110+
{
111+
CopyToDBNullAsNull(values.Span, values.Span);
112+
return values;
113+
}
98114

99115
/// <inheritdoc cref="ReplaceDBNullWithNull(Span{object?})"/>
100116
public static object?[] ReplaceDBNullWithNull(this object?[] values)
@@ -106,6 +122,30 @@ internal static IEnumerable<T> Concat<T>(T first, ICollection<T> remaining)
106122
return values;
107123
}
108124

125+
/// <inheritdoc cref="ReplaceDBNullWithNull(Span{object?})"/>
126+
public static List<object?> ReplaceDBNullWithNull(this List<object?> values)
127+
{
128+
if (values is null) throw new ArgumentNullException(nameof(values));
129+
Contract.EndContractBlock();
130+
131+
#if NET8_0_OR_GREATER
132+
var span = System.Runtime.InteropServices.CollectionsMarshal.AsSpan(values);
133+
for (int i = 0; i < span.Length; i++)
134+
{
135+
ref object? item = ref span[i];
136+
if (item == DBNull.Value) item = null;
137+
}
138+
#else
139+
int count = values.Count;
140+
for (int i = 0; i < count; i++)
141+
{
142+
if (values[i] == DBNull.Value) values[i] = null;
143+
}
144+
#endif
145+
146+
return values;
147+
}
148+
109149
/// <summary>
110150
/// Generic enumerable extension for <see cref="DataColumnCollection"/>.
111151
/// </summary>
@@ -149,7 +189,11 @@ static IEnumerable<DataRow> AsEnumerableCore(DataRowCollection rows)
149189
.Results(table, clearSourceTable);
150190

151191
/// <inheritdoc cref="To{T}(DataTable, IEnumerable{KeyValuePair{string, string?}}?, bool)"/>
192+
#if NET8_0_OR_GREATER
193+
public static IEnumerable<T> To<T>(this DataTable table, params IEnumerable<(string Field, string? Column)> fieldMappingOverrides) where T : new()
194+
#else
152195
public static IEnumerable<T> To<T>(this DataTable table, params (string Field, string? Column)[] fieldMappingOverrides) where T : new()
196+
#endif
153197
=> Transformer<T>
154198
.Create(fieldMappingOverrides)
155199
.Results(table, false);

0 commit comments

Comments
 (0)