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

loresoft / FluentCommand / 8850661434

26 Apr 2024 03:30PM UTC coverage: 54.48% (+2.6%) from 51.881%
8850661434

push

github

pwelter34
update debug settings

1152 of 2717 branches covered (42.4%)

Branch coverage included in aggregate %.

3682 of 6156 relevant lines covered (59.81%)

701.76 hits per line

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

56.82
/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
        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)
27✔
243
        {
244
            bool hasNextResult = _reader.NextResult();
18✔
245
            if (!hasNextResult)
18!
246
                throw new InvalidOperationException("The data reader could not advance to the next result.");
×
247
        }
248

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

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

261
        _readCount++;
27✔
262
    }
27✔
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