• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / FluentCommand / 8973726646

06 May 2024 06:14PM UTC coverage: 53.644% (-0.8%) from 54.48%
8973726646

push

github

pwelter34
fix test snapshots

1165 of 2845 branches covered (40.95%)

Branch coverage included in aggregate %.

3686 of 6198 relevant lines covered (59.47%)

697.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.14
/src/FluentCommand/QueryMultipleResult.cs
1
using System.Data;
2
using System.Data.Common;
3

4
using FluentCommand.Extensions;
5

6
namespace FluentCommand;
7

8
/// <summary>
9
/// Query class to wrap multiple results.
10
/// </summary>
11
internal class QueryMultipleResult : DisposableBase, IDataQuery, IDataQueryAsync
12
{
13
    private readonly DbDataReader _reader;
14
    private int _readCount;
15

16
    /// <summary>
17
    /// Initializes a new instance of the <see cref="QueryMultipleResult"/> class.
18
    /// </summary>
19
    /// <param name="reader">The reader.</param>
20
    internal QueryMultipleResult(DbDataReader reader)
18✔
21
    {
22
        _readCount = 0;
18✔
23
        _reader = reader;
18✔
24
    }
18✔
25

26
    /// <summary>
27
    /// Executes the command against the connection and converts the results to <typeparamref name="TEntity" /> objects.
28
    /// </summary>
29
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
30
    /// <param name="factory">The <see langword="delegate" /> factory to convert the <see cref="T:System.Data.IDataReader" /> to <typeparamref name="TEntity" />.</param>
31
    /// <param name="commandBehavior">Provides a description of the results of the query and its effect on the database.</param>
32
    /// <returns>
33
    /// An <see cref="T:System.Collections.Generic.IEnumerable`1" /> of <typeparamref name="TEntity" /> objects.
34
    /// </returns>
35
    public IEnumerable<TEntity> Query<TEntity>(
36
        Func<IDataReader, TEntity> factory,
37
        CommandBehavior commandBehavior = CommandBehavior.Default)
38
    {
39
        NextResult();
18✔
40

41
        var results = new List<TEntity>();
18✔
42
        while (_reader.Read())
72✔
43
        {
44
            var entity = factory(_reader);
54✔
45
            results.Add(entity);
54✔
46
        }
47

48
        return results;
18✔
49
    }
50

51
    /// <summary>
52
    /// Executes the command against the connection and converts the results to <typeparamref name="TEntity" /> objects asynchronously.
53
    /// </summary>
54
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
55
    /// <param name="factory">The <see langword="delegate" /> factory to convert the <see cref="T:System.Data.IDataReader" /> to <typeparamref name="TEntity" />.</param>
56
    /// <param name="commandBehavior">Provides a description of the results of the query and its effect on the database.</param>
57
    /// <param name="cancellationToken">The cancellation instruction.</param>
58
    /// <returns>
59
    /// An <see cref="T:System.Collections.Generic.IEnumerable`1" /> of <typeparamref name="TEntity" /> objects.
60
    /// </returns>
61
    public async Task<IEnumerable<TEntity>> QueryAsync<TEntity>(
62
        Func<IDataReader, TEntity> factory,
63
        CommandBehavior commandBehavior = CommandBehavior.Default,
64
        CancellationToken cancellationToken = default)
65
    {
66
        await NextResultAsync(cancellationToken).ConfigureAwait(false);
18✔
67

68
        var results = new List<TEntity>();
18✔
69
        while (await _reader.ReadAsync(cancellationToken).ConfigureAwait(false))
72✔
70
        {
71
            var entity = factory(_reader);
54✔
72
            results.Add(entity);
54✔
73
        }
74

75
        return results;
18✔
76
    }
18✔
77

78

79
    /// <summary>
80
    /// Executes the query and returns the first row in the result as a <typeparamref name="TEntity" /> object.
81
    /// </summary>
82
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
83
    /// <param name="factory">The <see langword="delegate" /> factory to convert the <see cref="T:System.Data.IDataReader" /> to <typeparamref name="TEntity" />.</param>
84
    /// <param name="commandBehavior">Provides a description of the results of the query and its effect on the database.</param>
85
    /// <returns>
86
    /// A instance of <typeparamref name="TEntity" /> if row exists; otherwise null.
87
    /// </returns>
88
    public TEntity QuerySingle<TEntity>(
89
        Func<IDataReader, TEntity> factory,
90
        CommandBehavior commandBehavior = CommandBehavior.Default)
91
    {
92
        NextResult();
9✔
93

94
        var result = _reader.Read()
9!
95
            ? factory(_reader)
9✔
96
            : default;
9✔
97

98
        return result;
9✔
99
    }
100

101
    /// <summary>
102
    /// Executes the query and returns the first row in the result as a <typeparamref name="TEntity" /> object asynchronously.
103
    /// </summary>
104
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
105
    /// <param name="factory">The <see langword="delegate" /> factory to convert the <see cref="T:System.Data.IDataReader" /> to <typeparamref name="TEntity" />.</param>
106
    /// <param name="commandBehavior">Provides a description of the results of the query and its effect on the database.</param>
107
    /// <param name="cancellationToken">The cancellation instruction.</param>
108
    /// <returns>
109
    /// A instance of <typeparamref name="TEntity" /> if row exists; otherwise null.
110
    /// </returns>
111
    public async Task<TEntity> QuerySingleAsync<TEntity>(
112
        Func<IDataReader, TEntity> factory,
113
        CommandBehavior commandBehavior = CommandBehavior.Default,
114
        CancellationToken cancellationToken = default)
115
    {
116
        await NextResultAsync(cancellationToken).ConfigureAwait(false);
9✔
117

118
        var result = await _reader.ReadAsync(cancellationToken).ConfigureAwait(false)
9!
119
            ? factory(_reader)
9✔
120
            : default;
9✔
121

122
        return result;
9✔
123
    }
9✔
124

125

126
    /// <summary>
127
    /// Executes the query and returns the first column of the first row in the result set returned by the query. All other columns and rows are ignored.
128
    /// </summary>
129
    /// <typeparam name="TValue">The type of the value.</typeparam>
130
    /// <param name="convert">The <see langword="delegate" /> to convert the value..</param>
131
    /// <returns>
132
    /// The value of the first column of the first row in the result set.
133
    /// </returns>
134
    public TValue QueryValue<TValue>(Func<object, TValue> convert)
135
    {
136
        NextResult();
×
137

138
        var result = _reader.Read()
×
139
            ? _reader.GetValue(0)
×
140
            : default(TValue);
×
141

142
        return ConvertExtensions.ConvertValue(result, convert);
×
143
    }
144

145
    /// <summary>
146
    /// Executes the query and returns the first column of the first row in the result set returned by the query asynchronously. All other columns and rows are ignored.
147
    /// </summary>
148
    /// <typeparam name="TValue">The type of the value.</typeparam>
149
    /// <param name="convert">The <see langword="delegate" /> to convert the value..</param>
150
    /// <param name="cancellationToken">The cancellation instruction.</param>
151
    /// <returns>
152
    /// The value of the first column of the first row in the result set.
153
    /// </returns>
154
    public async Task<TValue> QueryValueAsync<TValue>(
155
        Func<object, TValue> convert,
156
        CancellationToken cancellationToken = default)
157
    {
158
        await NextResultAsync(cancellationToken).ConfigureAwait(false);
×
159

160
        var result = await _reader.ReadAsync(cancellationToken).ConfigureAwait(false)
×
161
            ? _reader.GetValue(0)
×
162
            : default(TValue);
×
163

164
        return ConvertExtensions.ConvertValue(result, convert);
×
165
    }
×
166

167

168
    /// <summary>
169
    /// Executes the command against the connection and converts the results to a <see cref="DataTable" />.
170
    /// </summary>
171
    /// <returns>
172
    /// A <see cref="DataTable" /> of the results.
173
    /// </returns>
174
    public DataTable QueryTable()
175
    {
176
        NextResult();
×
177

178
        var dataTable = new DataTable();
×
179
        dataTable.Load(_reader);
×
180

181
        return dataTable;
×
182
    }
183

184

185
    /// <summary>
186
    /// Executes the command against the connection and converts the results to a <see cref="DataTable" /> asynchronously.
187
    /// </summary>
188
    /// <param name="cancellationToken">The cancellation instruction.</param>
189
    /// <returns>
190
    /// A <see cref="DataTable" /> of the results.
191
    /// </returns>
192
    public async Task<DataTable> QueryTableAsync(CancellationToken cancellationToken = default)
193
    {
194
        await NextResultAsync(cancellationToken).ConfigureAwait(false);
×
195

196
        var dataTable = new DataTable();
×
197
        dataTable.Load(_reader);
×
198

199
        return dataTable;
×
200
    }
×
201

202
    /// <summary>
203
    /// Executes the command against the connection and sends the resulting <see cref="IDataReader" /> to the readAction delegate.
204
    /// </summary>
205
    /// <param name="readAction">The read action delegate to pass the open <see cref="IDataReader" />.</param>
206
    /// <param name="commandBehavior">Provides a description of the results of the query and its effect on the database.</param>
207
    /// <exception cref="System.NotImplementedException"></exception>
208
    public void Read(
209
        Action<IDataReader> readAction,
210
        CommandBehavior commandBehavior = CommandBehavior.Default)
211
    {
212
        NextResult();
×
213

214
        readAction(_reader);
×
215
    }
×
216

217
    /// <summary>
218
    /// Executes the command against the connection and sends the resulting <see cref="IDataReader" /> to the readAction delegate.
219
    /// </summary>
220
    /// <param name="readAction">The read action delegate to pass the open <see cref="IDataReader" />.</param>
221
    /// <param name="commandBehavior">Provides a description of the results of the query and its effect on the database.</param>
222
    /// <param name="cancellationToken">The cancellation instruction.</param>
223
    /// <returns></returns>
224
    /// <exception cref="System.NotImplementedException"></exception>
225
    public async Task ReadAsync(
226
        Func<IDataReader, CancellationToken, Task> readAction,
227
        CommandBehavior commandBehavior = CommandBehavior.Default,
228
        CancellationToken cancellationToken = default)
229
    {
230
        await NextResultAsync(cancellationToken);
×
231

232
        await readAction(_reader, cancellationToken);
×
233
    }
×
234

235

236
    private void NextResult()
237
    {
238
        if (_readCount > 0)
27✔
239
        {
240
            bool hasNextResult = _reader.NextResult();
18✔
241
            if (!hasNextResult)
18!
242
                throw new InvalidOperationException("The data reader could not advance to the next result.");
×
243
        }
244

245
        _readCount++;
27✔
246
    }
27✔
247

248
    private async Task NextResultAsync(CancellationToken cancellationToken)
249
    {
250
        if (_readCount > 0)
27✔
251
        {
252
            bool hasNextResult = await _reader.NextResultAsync(cancellationToken).ConfigureAwait(false);
18✔
253
            if (!hasNextResult)
18!
254
                throw new InvalidOperationException("The data reader could not advance to the next result.");
×
255
        }
256

257
        _readCount++;
27✔
258
    }
27✔
259

260
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc