• 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

69.41
/src/FluentCommand.Json/JsonCommandExtensions.cs
1
using System.Buffers;
2
using System.Data;
3
using System.Data.Common;
4
using System.Text;
5
using System.Text.Json;
6

7
using Microsoft.IO;
8

9
namespace FluentCommand;
10

11
/// <summary>
12
/// Extension methods for <see cref="IDataCommand"/>
13
/// </summary>
14
public static class JsonCommandExtensions
15
{
16
    private static readonly RecyclableMemoryStreamManager _memoryStreamManager = new();
3✔
17

18
    /// <summary>
19
    /// Executes the query and returns a JSON string from data set returned by the query.
20
    /// </summary>
21
    /// <param name="dataCommand">The data command.</param>
22
    /// <param name="options">The <see cref="JsonWriterOptions" /> options.</param>
23
    /// <returns>
24
    /// A JSON string representing the <see cref="IDataReader" /> result of the command.
25
    /// </returns>
26
    public static string QueryJson(this IDataCommand dataCommand, JsonWriterOptions options = default)
27
    {
28
        if (dataCommand is null)
3!
29
            throw new ArgumentNullException(nameof(dataCommand));
×
30

31
        using var stream = _memoryStreamManager.GetStream();
3✔
32

33
        QueryJson(dataCommand, stream, options);
3✔
34

35
        var bytes = stream.GetReadOnlySequence();
3✔
36

37
#if NET5_0_OR_GREATER
38
        return Encoding.UTF8.GetString(bytes);
3✔
39
#else
40
        return Encoding.UTF8.GetString(bytes.ToArray());
41
#endif
42
    }
3✔
43

44
    /// <summary>
45
    /// Executes the query and returns a JSON string from data set returned by the query.
46
    /// </summary>
47
    /// <param name="dataCommand">The data command.</param>
48
    /// <param name="stream">The destination for writing JSON text.</param>
49
    /// <param name="options">The <see cref="JsonWriterOptions" /> options.</param>
50
    /// <returns>
51
    /// A JSON string representing the <see cref="IDataReader" /> result of the command.
52
    /// </returns>
53
    public static void QueryJson(this IDataCommand dataCommand, Stream stream, JsonWriterOptions options = default)
54
    {
55
        if (dataCommand is null)
6!
56
            throw new ArgumentNullException(nameof(dataCommand));
×
57
        if (stream is null)
6!
58
            throw new ArgumentNullException(nameof(stream));
×
59

60
        var writer = new Utf8JsonWriter(stream, options);
6✔
61

62
        writer.WriteStartArray();
6✔
63

64
        dataCommand.Read(reader => WriteData(reader, writer), CommandBehavior.SequentialAccess | CommandBehavior.SingleResult);
12✔
65

66
        writer.WriteEndArray();
6✔
67

68
        writer.Flush();
6✔
69
    }
6✔
70

71

72
    /// <summary>
73
    /// Executes the query and returns a JSON string from data set returned by the query asynchronously.
74
    /// </summary>
75
    /// <param name="dataCommand">The data command.</param>
76
    /// <param name="options">The <see cref="JsonWriterOptions" /> options.</param>
77
    /// <param name="cancellationToken">The cancellation token.</param>
78
    /// <returns>
79
    /// A JSON string representing the <see cref="IDataReader" /> result of the command.
80
    /// </returns>
81
    public static async Task<string> QueryJsonAsync(this IDataCommand dataCommand, JsonWriterOptions options = default, CancellationToken cancellationToken = default)
82
    {
83
        if (dataCommand is null)
6!
84
            throw new ArgumentNullException(nameof(dataCommand));
×
85

86
        using var stream = _memoryStreamManager.GetStream();
6✔
87

88
        await QueryJsonAsync(dataCommand, stream, options, cancellationToken);
6✔
89

90
        var bytes = stream.GetReadOnlySequence();
6✔
91

92
#if NET5_0_OR_GREATER
93
        return Encoding.UTF8.GetString(bytes);
6✔
94
#else
95
        return Encoding.UTF8.GetString(bytes.ToArray());
96
#endif
97

98
    }
6✔
99

100
    /// <summary>
101
    /// Executes the query and returns a JSON string from data set returned by the query asynchronously.
102
    /// </summary>
103
    /// <param name="dataCommand">The data command.</param>
104
    /// <param name="stream">The destination for writing JSON text.</param>
105
    /// <param name="options">The <see cref="JsonWriterOptions" /> options.</param>
106
    /// <param name="cancellationToken">The cancellation token.</param>
107
    /// <returns>
108
    /// A JSON string representing the <see cref="IDataReader" /> result of the command.
109
    /// </returns>
110
    public static async Task QueryJsonAsync(this IDataCommand dataCommand, Stream stream, JsonWriterOptions options = default, CancellationToken cancellationToken = default)
111
    {
112
        if (dataCommand is null)
9!
113
            throw new ArgumentNullException(nameof(dataCommand));
×
114
        if (stream is null)
9!
115
            throw new ArgumentNullException(nameof(stream));
×
116

117
        var writer = new Utf8JsonWriter(stream, options);
9✔
118

119
        writer.WriteStartArray();
9✔
120

121
        await dataCommand.ReadAsync(async (reader, token) =>
9✔
122
        {
9✔
123
            if (reader is DbDataReader dataReader)
9!
124
                await WriteDataAsync(dataReader, writer, token);
9✔
125
            else
9✔
126
                WriteData(reader, writer);
×
127

9✔
128
        }, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult, cancellationToken);
18✔
129

130
        writer.WriteEndArray();
9✔
131

132
        await writer.FlushAsync(cancellationToken);
9✔
133
    }
9✔
134

135

136
    private static void WriteData(IDataReader reader, Utf8JsonWriter writer)
137
    {
138
        while (reader.Read())
6,006✔
139
        {
140
            WriteObject(reader, writer);
6,000✔
141
        }
142
    }
6✔
143

144
    private static async Task WriteDataAsync(DbDataReader reader, Utf8JsonWriter writer, CancellationToken cancellationToken = default)
145
    {
146
        while (await reader.ReadAsync(cancellationToken))
6,027✔
147
        {
148
            WriteObject(reader, writer);
6,018✔
149
        }
150
    }
9✔
151

152
    private static void WriteObject(IDataReader reader, Utf8JsonWriter writer)
153
    {
154
        writer.WriteStartObject();
12,018✔
155

156
        for (int index = 0; index < reader.FieldCount; index++)
480,396✔
157
        {
158
            var name = reader.GetName(index);
228,180✔
159
            writer.WritePropertyName(name);
228,180✔
160

161
            WriteValue(reader, writer, index);
228,180✔
162
        }
163

164
        writer.WriteEndObject();
12,018✔
165
    }
12,018✔
166

167
    private static void WriteValue(IDataReader reader, Utf8JsonWriter writer, int index)
168
    {
169
        if (reader.IsDBNull(index))
228,180✔
170
        {
171
            writer.WriteNullValue();
72,236✔
172
            return;
72,236✔
173
        }
174

175
        var type = reader.GetFieldType(index);
155,944✔
176

177
        if (type == typeof(string))
155,944✔
178
        {
179
            var value = reader.GetString(index);
59,836✔
180
            writer.WriteStringValue(value);
59,836✔
181
            return;
59,836✔
182
        }
183

184
        if (type == typeof(bool))
96,108✔
185
        {
186
            var value = reader.GetBoolean(index);
36,018✔
187
            writer.WriteBooleanValue(value);
36,018✔
188
            return;
36,018✔
189
        }
190

191
        if (type == typeof(byte))
60,090!
192
        {
193
            var value = reader.GetByte(index);
×
194
            writer.WriteNumberValue(value);
×
195
            return;
×
196
        }
197

198
        if (type == typeof(short))
60,090!
199
        {
200
            var value = reader.GetInt16(index);
×
201
            writer.WriteNumberValue(value);
×
202
            return;
×
203
        }
204

205
        if (type == typeof(int))
60,090✔
206
        {
207
            var value = reader.GetInt32(index);
12,036✔
208
            writer.WriteNumberValue(value);
12,036✔
209
            return;
12,036✔
210
        }
211

212
        if (type == typeof(long))
48,054!
213
        {
214
            var value = reader.GetInt64(index);
×
215
            writer.WriteNumberValue(value);
×
216
            return;
×
217
        }
218

219
        if (type == typeof(float))
48,054!
220
        {
221
            var value = reader.GetFloat(index);
×
222
            writer.WriteNumberValue(value);
×
223
            return;
×
224
        }
225

226
        if (type == typeof(double))
48,054!
227
        {
228
            var value = reader.GetDouble(index);
×
229
            writer.WriteNumberValue(value);
×
230
            return;
×
231
        }
232

233
        if (type == typeof(decimal))
48,054!
234
        {
235
            var value = reader.GetDecimal(index);
×
236
            writer.WriteNumberValue(value);
×
237
            return;
×
238
        }
239

240
        if (type == typeof(TimeSpan))
48,054!
241
        {
242
            var value = reader.GetDateTime(index);
×
243
            writer.WriteStringValue(value);
×
244
            return;
×
245
        }
246

247
        if (type == typeof(DateTime))
48,054!
248
        {
249
            var value = reader.GetDateTime(index);
×
250
            writer.WriteStringValue(value);
×
251
            return;
×
252
        }
253

254
        if (type == typeof(DateTimeOffset))
48,054✔
255
        {
256
            var value = reader.GetValue(index);
24,036✔
257
            if (value is DateTimeOffset offset)
24,036!
258
            {
259
                writer.WriteStringValue(offset);
24,036✔
260
                return;
24,036✔
261
            }
262

263
            var date = reader.GetDateTime(index);
×
264
            date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
×
265

266
            offset = new DateTimeOffset(date, TimeSpan.Zero);
×
267

268
            writer.WriteStringValue(offset);
×
269
            return;
×
270
        }
271

272
        if (type == typeof(Guid))
24,018✔
273
        {
274
            var value = reader.GetGuid(index);
12,000✔
275
            writer.WriteStringValue(value);
12,000✔
276
            return;
12,000✔
277
        }
278

279
        // fallback
280
        var v = reader.GetValue(index);
12,018✔
281
        writer.WriteStringValue(v.ToString());
12,018✔
282
    }
12,018✔
283
}
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