Skip to content

Commit 3b6fcd6

Browse files
Update naming styles, nullability, and tests
- Updated `.editorconfig` for new naming styles and diagnostic settings. - Removed `using System.Buffers;` in `ToChannel.Target.cs` and made `arrayPool` parameters nullable. - Enhanced `ToChannel` and `ToChannelAsync` methods with null checks for `arrayPool`. - Added a new constructor for `QueryResultQueue<T>` to initialize from an enumerable. - Simplified `Processor` constructor in `Transformer.cs` using expression-bodied syntax. - Made significant changes to `DataReaderExtensions` for nullable parameter support. - Introduced new test classes for `IDataReader` and `IDbCommand` to validate null handling and behavior. - Updated project file to include implicit usings and project references. - Created `_Imports.cs` for global using directives to streamline the codebase.
1 parent 73d40df commit 3b6fcd6

14 files changed

+560
-118
lines changed

.editorconfig

+7-1
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,11 @@ dotnet_diagnostic.CA1510.severity = silent
178178
# IDE0130: Namespace does not match folder structure
179179
dotnet_diagnostic.IDE0130.severity = silent
180180

181+
# IDE0301: Simplify collection initialization
182+
dotnet_diagnostic.IDE0301.severity = silent
183+
181184
# IDE0305: Simplify collection initialization
182-
dotnet_diagnostic.IDE0305.severity = silent
185+
dotnet_diagnostic.IDE0305.severity = silent
186+
187+
# IDE0306: Simplify collection initialization
188+
dotnet_diagnostic.IDE0306.severity = silent

Source/Channel/ToChannel.Target.cs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System.Buffers;
2-
3-
namespace Open.Database.Extensions;
1+
namespace Open.Database.Extensions;
42

53
/// <summary>
64
/// Extensions for writing data to a channel.
@@ -127,7 +125,7 @@ public static ValueTask<long> ToChannel(this IDataReader reader,
127125
public static ValueTask<long> ToChannel(this IDataReader reader,
128126
ChannelWriter<object[]> target,
129127
bool complete,
130-
ArrayPool<object> arrayPool,
128+
ArrayPool<object>? arrayPool,
131129
CancellationToken cancellationToken = default)
132130
{
133131
if (reader is null) throw new ArgumentNullException(nameof(reader));
@@ -546,7 +544,7 @@ public static ValueTask<long> ToChannelAsync(this DbDataReader reader,
546544
public static ValueTask<long> ToChannelAsync(this DbDataReader reader,
547545
ChannelWriter<object[]> target,
548546
bool complete,
549-
ArrayPool<object> arrayPool,
547+
ArrayPool<object>? arrayPool,
550548
CancellationToken cancellationToken = default)
551549
{
552550
if (reader is null) throw new ArgumentNullException(nameof(reader));
@@ -758,7 +756,7 @@ public static ValueTask<long> ToChannelAsync(this IExecuteReaderAsync command,
758756
public static ValueTask<long> ToChannelAsync(this IExecuteReaderAsync command,
759757
ChannelWriter<object[]> target,
760758
bool complete,
761-
ArrayPool<object> arrayPool)
759+
ArrayPool<object>? arrayPool)
762760
=> ToChannelAsyncCore(
763761
command, target, complete,
764762
reader => command.UseAsyncRead && reader is DbDataReader r

Source/Channel/ToChannel.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ public static ChannelReader<object[]> ToChannel(this IDataReader reader,
3535
/// <returns>The channel reader containing the results.</returns>
3636
public static ChannelReader<object[]> ToChannel(this IDataReader reader,
3737
bool singleReader,
38-
ArrayPool<object> arrayPool,
38+
ArrayPool<object>? arrayPool,
3939
CancellationToken cancellationToken = default)
4040
{
4141
if (reader is null) throw new ArgumentNullException(nameof(reader));
42-
if (arrayPool is null) throw new ArgumentNullException(nameof(arrayPool));
4342
Contract.EndContractBlock();
4443

4544
Channel<object[]> channel = CreateChannel<object[]>(-1, singleReader);
@@ -580,7 +579,7 @@ public static ChannelReader<object[]> ToChannelAsync(this IExecuteReaderAsync co
580579
/// <returns>The channel reader containing the results.</returns>
581580
public static ChannelReader<object[]> ToChannelAsync(this IExecuteReaderAsync command,
582581
bool singleReader,
583-
ArrayPool<object> arrayPool)
582+
ArrayPool<object>? arrayPool)
584583
{
585584
if (command is null) throw new ArgumentNullException(nameof(command));
586585
Contract.EndContractBlock();

Source/Core/Core/QueryResult.cs

+9
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ public QueryResultQueue(
158158
: base(ordinals, names, result)
159159
{
160160
}
161+
162+
/// <inheritdoc cref="QueryResultQueue{T}.QueryResultQueue(ImmutableArray{int}, ImmutableArray{string}, Queue{T})" />
163+
public QueryResultQueue(
164+
IEnumerable<int> ordinals,
165+
IEnumerable<string> names,
166+
IEnumerable<T> result)
167+
: base(ordinals, names, new (result))
168+
{
169+
}
161170
}
162171

163172
/// <summary>

Source/Core/Core/Transformer.cs

+1-6
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,7 @@ public Processor(Transformer<T> transformer)
116116
/// <param name="transformer">The transformer to use.</param>
117117
/// <param name="names">The names of columns/properties to acquire.</param>
118118
public Processor(Transformer<T> transformer, ImmutableArray<string> names)
119-
: this(transformer)
120-
{
121-
SetNames(names);
122-
}
119+
: this(transformer) => SetNames(names);
123120

124121
/// <summary>
125122
/// The transformer being used.
@@ -260,9 +257,7 @@ async IAsyncEnumerable<T> ResultsAsyncCore(DbDataReader reader, [EnumeratorCance
260257
(string Name, int Ordinal)[] columns = reader.GetMatchingOrdinals(_propertyMap.Values, true);
261258
var processor = new Processor(this, columns.Select(m => m.Name).ToImmutableArray());
262259

263-
#pragma warning disable ConfigureAwaitEnforcer // ConfigureAwaitEnforcer
264260
await foreach (object[] a in reader.AsAsyncEnumerable(columns.Select(m => m.Ordinal), LocalPool, cancellationToken))
265-
#pragma warning restore ConfigureAwaitEnforcer // ConfigureAwaitEnforcer
266261
{
267262
try
268263
{

Source/Core/ExpressiveCommandBase.Param.cs

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public override readonly bool Equals(object? obj)
4141

4242
/// <inheritdoc />
4343
#if NETSTANDARD2_0
44+
[SuppressMessage("Roslynator", "RCS1123:Add parentheses when necessary", Justification = "<Pending>")]
4445
public override readonly int GetHashCode()
4546
{
4647
int hashCode = 1477810893;

Source/Core/Extensions/DataReader.cs

+109-86
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Open.Database.Extensions;
1+
using System.Diagnostics;
2+
3+
namespace Open.Database.Extensions;
24

35
/// <summary>
46
/// Extension methods for Data Readers.
@@ -140,113 +142,131 @@ public static async ValueTask ForEachAsync(
140142
public static ValueTask ForEachAsync(this DbDataReader reader, Func<IDataRecord, ValueTask> handler, CancellationToken cancellationToken)
141143
=> ForEachAsync(reader, handler, true, cancellationToken);
142144

143-
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
144-
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader)
145+
static IEnumerable<object[]> AsEnumerableCore(IDataReader reader)
145146
{
146-
return reader is null
147-
? throw new ArgumentNullException(nameof(reader))
148-
: AsEnumerableCore(reader);
147+
Debug.Assert(reader is not null);
148+
149+
if (!reader.Read())
150+
yield break;
149151

150-
static IEnumerable<object[]> AsEnumerableCore(IDataReader reader)
152+
int fieldCount = reader.FieldCount;
153+
do
151154
{
152-
if (!reader.Read())
153-
yield break;
155+
object[] row = new object[fieldCount];
156+
reader.GetValues(row);
157+
yield return row;
158+
} while (reader.Read());
159+
}
154160

155-
int fieldCount = reader.FieldCount;
156-
do
157-
{
158-
object[] row = new object[fieldCount];
159-
reader.GetValues(row);
160-
yield return row;
161-
} while (reader.Read());
162-
}
161+
static IEnumerable<object[]> AsEnumerableCore(IDataReader reader, ArrayPool<object> arrayPool)
162+
{
163+
Debug.Assert(reader is not null);
164+
Debug.Assert(arrayPool is not null);
165+
166+
if (!reader.Read())
167+
yield break;
168+
169+
int fieldCount = reader.FieldCount;
170+
do
171+
{
172+
object[] row = arrayPool.Rent(fieldCount);
173+
reader.GetValues(row);
174+
yield return row;
175+
} while (reader.Read());
163176
}
164177

165178
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
166-
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, ArrayPool<object> arrayPool)
167-
{
168-
return reader is null
179+
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader)
180+
=> reader is null
181+
? throw new ArgumentNullException(nameof(reader))
182+
: AsEnumerableCore(reader);
183+
184+
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
185+
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, ArrayPool<object>? arrayPool)
186+
=> reader is null
169187
? throw new ArgumentNullException(nameof(reader))
170188
: arrayPool is null
171-
? throw new ArgumentNullException(nameof(arrayPool))
189+
? AsEnumerableCore(reader)
172190
: AsEnumerableCore(reader, arrayPool);
173191

174-
static IEnumerable<object[]> AsEnumerableCore(IDataReader reader, ArrayPool<object> arrayPool)
175-
{
176-
if (!reader.Read())
177-
yield break;
192+
static IEnumerable<object[]> AsEnumerableInternalCore(
193+
IDataReader reader, IEnumerable<int> ordinals, bool readStarted)
194+
{
195+
Debug.Assert(reader is not null);
196+
Debug.Assert(ordinals is not null);
178197

179-
int fieldCount = reader.FieldCount;
198+
if (!readStarted && !reader.Read())
199+
yield break;
200+
201+
IList<int> o = ordinals as IList<int> ?? ordinals.ToArray();
202+
int fieldCount = o.Count;
203+
if (fieldCount == 0)
204+
{
180205
do
181206
{
182-
object[] row = arrayPool.Rent(fieldCount);
183-
reader.GetValues(row);
184-
yield return row;
185-
} while (reader.Read());
207+
yield return Array.Empty<object>();
208+
}
209+
while (reader.Read());
210+
yield break;
186211
}
212+
213+
do
214+
{
215+
object[] row = new object[fieldCount];
216+
for (int i = 0; i < fieldCount; i++)
217+
row[i] = reader.GetValue(o[i]);
218+
yield return row;
219+
}
220+
while (reader.Read());
187221
}
188222

189-
internal static IEnumerable<object[]> AsEnumerableInternal(this IDataReader reader, IEnumerable<int> ordinals, bool readStarted)
223+
static IEnumerable<object[]> AsEnumerableInternalCore(
224+
IDataReader reader, IEnumerable<int> ordinals, bool readStarted, ArrayPool<object> arrayPool)
190225
{
191-
return reader is null
192-
? throw new ArgumentNullException(nameof(reader))
193-
: ordinals is null
194-
? throw new ArgumentNullException(nameof(ordinals))
195-
: AsEnumerableInternalCore(reader, ordinals, readStarted);
226+
Debug.Assert(reader is not null);
227+
Debug.Assert(ordinals is not null);
228+
Debug.Assert(arrayPool is not null);
196229

197-
static IEnumerable<object[]> AsEnumerableInternalCore(IDataReader reader, IEnumerable<int> ordinals, bool readStarted)
198-
{
199-
if (!readStarted && !reader.Read())
200-
yield break;
230+
if (!readStarted && !reader.Read())
231+
yield break;
201232

202-
IList<int> o = ordinals as IList<int> ?? ordinals.ToArray();
203-
int fieldCount = o.Count;
204-
if (fieldCount == 0)
205-
{
206-
do
207-
{
208-
yield return Array.Empty<object>();
209-
}
210-
while (reader.Read());
211-
yield break;
212-
}
213-
214-
do
215-
{
216-
object[] row = new object[fieldCount];
217-
for (int i = 0; i < fieldCount; i++)
218-
row[i] = reader.GetValue(o[i]);
219-
yield return row;
220-
}
221-
while (reader.Read());
233+
IList<int> o = ordinals as IList<int> ?? ordinals.ToArray();
234+
int fieldCount = o.Count;
235+
do
236+
{
237+
object[] row = arrayPool.Rent(fieldCount);
238+
for (int i = 0; i < fieldCount; i++)
239+
row[i] = reader.GetValue(o[i]);
240+
yield return row;
222241
}
242+
while (reader.Read());
223243
}
224244

225-
internal static IEnumerable<object[]> AsEnumerableInternal(this IDataReader reader, IEnumerable<int> ordinals, bool readStarted, ArrayPool<object> arrayPool)
245+
internal static IEnumerable<object[]> AsEnumerableInternal(
246+
this IDataReader reader,
247+
IEnumerable<int> ordinals,
248+
bool readStarted)
226249
{
227-
return reader is null
228-
? throw new ArgumentNullException(nameof(reader))
229-
: ordinals is null
230-
? throw new ArgumentNullException(nameof(ordinals))
231-
: arrayPool is null ? throw new ArgumentNullException(nameof(arrayPool))
232-
: AsEnumerableInternalCore();
250+
if (reader is null) throw new ArgumentNullException(nameof(reader));
251+
if (ordinals is null) throw new ArgumentNullException(nameof(ordinals));
252+
Contract.EndContractBlock();
233253

234-
IEnumerable<object[]> AsEnumerableInternalCore()
235-
{
236-
if (!readStarted && !reader.Read())
237-
yield break;
254+
return AsEnumerableInternalCore(reader, ordinals, readStarted);
255+
}
238256

239-
IList<int> o = ordinals as IList<int> ?? ordinals.ToArray();
240-
int fieldCount = o.Count;
241-
do
242-
{
243-
object[] row = arrayPool.Rent(fieldCount);
244-
for (int i = 0; i < fieldCount; i++)
245-
row[i] = reader.GetValue(o[i]);
246-
yield return row;
247-
}
248-
while (reader.Read());
249-
}
257+
internal static IEnumerable<object[]> AsEnumerableInternal(
258+
this IDataReader reader,
259+
IEnumerable<int> ordinals,
260+
bool readStarted,
261+
ArrayPool<object>? arrayPool)
262+
{
263+
if (reader is null) throw new ArgumentNullException(nameof(reader));
264+
if (ordinals is null) throw new ArgumentNullException(nameof(ordinals));
265+
Contract.EndContractBlock();
266+
267+
return arrayPool is null
268+
? AsEnumerableInternalCore(reader, ordinals, readStarted)
269+
: AsEnumerableInternalCore(reader, ordinals, readStarted, arrayPool);
250270
}
251271

252272
/// <inheritdoc cref="AsEnumerable(IDataReader, IEnumerable{int}, ArrayPool{object?})"/>
@@ -257,7 +277,7 @@ public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, IEnume
257277
/// <param name="ordinals">The limited set of ordinals to include. If none are specified, the returned objects will be empty.</param>
258278
/// <param name="arrayPool">The array pool to acquire buffers from.</param>
259279
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
260-
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, IEnumerable<int> ordinals, ArrayPool<object> arrayPool)
280+
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, IEnumerable<int> ordinals, ArrayPool<object>? arrayPool)
261281
=> AsEnumerableInternal(reader, ordinals, false, arrayPool);
262282

263283
/// <param name="reader">The reader to enumerate.</param>
@@ -276,7 +296,7 @@ public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, int n,
276296
/// <param name="n">The first ordinal to include in the request to the reader for each record.</param>
277297
/// <param name="others">The remaining ordinals to request from the reader for each record.</param>
278298
/// <returns>An enumerable of the values returned from a data reader.</returns>
279-
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, ArrayPool<object> arrayPool, int n, params int[] others)
299+
public static IEnumerable<object[]> AsEnumerable(this IDataReader reader, ArrayPool<object>? arrayPool, int n, params int[] others)
280300
=> AsEnumerable(reader, CoreExtensions.Concat(n, others), arrayPool);
281301

282302
/// <inheritdoc cref="Select{T}(IDataReader, Func{IDataRecord, T}, CancellationToken, bool)"/>
@@ -392,12 +412,15 @@ static async IAsyncEnumerable<object[]> AsAsyncEnumerableCore(DbDataReader reade
392412
/// <param name="arrayPool">An optional array pool to acquire buffers from.</param>
393413
/// <param name="cancellationToken">Optional iteration cancellation token.</param>
394414
/// <inheritdoc cref="AsEnumerable(IDataReader, ArrayPool{object?}, int, int[])"/>
395-
public static IAsyncEnumerable<object[]> AsAsyncEnumerable(this DbDataReader reader, ArrayPool<object> arrayPool, CancellationToken cancellationToken = default)
415+
public static IAsyncEnumerable<object[]> AsAsyncEnumerable(
416+
this DbDataReader reader,
417+
ArrayPool<object>? arrayPool,
418+
CancellationToken cancellationToken = default)
396419
{
397420
return reader is null
398421
? throw new ArgumentNullException(nameof(reader))
399422
: arrayPool is null
400-
? throw new ArgumentNullException(nameof(arrayPool))
423+
? AsAsyncEnumerable(reader, cancellationToken)
401424
: AsAsyncEnumerableCore(reader, arrayPool, cancellationToken);
402425

403426
static async IAsyncEnumerable<object[]> AsAsyncEnumerableCore(DbDataReader reader, ArrayPool<object> arrayPool, [EnumeratorCancellation] CancellationToken cancellationToken)

0 commit comments

Comments
 (0)