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

loresoft / FluentCommand / 5874771988

16 Aug 2023 04:44AM UTC coverage: 43.028% (+2.5%) from 40.495%
5874771988

push

github

web-flow
Merge pull request #277 from loresoft/feature/method-injectors

Feature/method injectors

765 of 2171 branches covered (35.24%)

Branch coverage included in aggregate %.

126 of 126 new or added lines in 6 files covered. (100.0%)

2361 of 5094 relevant lines covered (46.35%)

119.69 hits per line

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

59.09
/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)
6✔
21
    {
22
        _readCount = 0;
6✔
23
        _reader = reader;
6✔
24
    }
6✔
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();
6✔
40

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

48
        return results;
6✔
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);
67

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

75
        return results;
76
    }
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();
3✔
93

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

98
        return result;
3✔
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);
117

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

122
        return result;
123
    }
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
        var value = result.ConvertValue(convert);
×
143

144
        return value;
×
145
    }
146

147
    /// <summary>
148
    /// 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.
149
    /// </summary>
150
    /// <typeparam name="TValue">The type of the value.</typeparam>
151
    /// <param name="convert">The <see langword="delegate" /> to convert the value..</param>
152
    /// <param name="cancellationToken">The cancellation instruction.</param>
153
    /// <returns>
154
    /// The value of the first column of the first row in the result set.
155
    /// </returns>
156
    public async Task<TValue> QueryValueAsync<TValue>(
157
        Func<object, TValue> convert,
158
        CancellationToken cancellationToken = default)
159
    {
160
        await NextResultAsync(cancellationToken).ConfigureAwait(false);
161

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

166
        var value = result.ConvertValue(convert);
167

168
        return value;
169
    }
170

171

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

182
        var dataTable = new DataTable();
×
183
        dataTable.Load(_reader);
×
184

185
        return dataTable;
×
186
    }
187

188

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

200
        var dataTable = new DataTable();
201
        dataTable.Load(_reader);
202

203
        return dataTable;
204
    }
205

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

218
        readAction(_reader);
×
219
    }
×
220

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

236
        await readAction(_reader, cancellationToken);
237
    }
238

239

240
    private void NextResult()
241
    {
242
        if (_readCount > 0)
9✔
243
        {
244
            bool hasNextResult = _reader.NextResult();
6✔
245
            if (!hasNextResult)
6!
246
                throw new InvalidOperationException("The data reader could not advance to the next result.");
×
247
        }
248

249
        _readCount++;
9✔
250
    }
9✔
251

252
    private async Task NextResultAsync(CancellationToken cancellationToken)
253
    {
254
        if (_readCount > 0)
255
        {
256
            bool hasNextResult = await _reader.NextResultAsync(cancellationToken).ConfigureAwait(false);
257
            if (!hasNextResult)
258
                throw new InvalidOperationException("The data reader could not advance to the next result.");
259
        }
260

261
        _readCount++;
262
    }
263

264
}
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