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

loresoft / FluentCommand / 9074741070

14 May 2024 06:23AM UTC coverage: 54.074% (+0.4%) from 53.649%
9074741070

push

github

pwelter34
Update DataMergeGeneratorTests.BuildTableSqlTest.verified.txt

1186 of 2873 branches covered (41.28%)

Branch coverage included in aggregate %.

3732 of 6222 relevant lines covered (59.98%)

716.09 hits per line

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

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

9
using FluentCommand.Extensions;
10

11
using Microsoft.IO;
12

13
namespace FluentCommand;
14

15
/// <summary>
16
/// Extension methods for <see cref="IDataCommand"/>
17
/// </summary>
18
public static class JsonCommandExtensions
19
{
20
    private static readonly RecyclableMemoryStreamManager _memoryStreamManager = new();
3✔
21

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

35
        using var stream = _memoryStreamManager.GetStream();
3✔
36

37
        QueryJson(dataCommand, stream, options);
3✔
38

39
        var bytes = stream.GetReadOnlySequence();
3✔
40

41
#if NET5_0_OR_GREATER
42
        return Encoding.UTF8.GetString(bytes);
3✔
43
#else
44
        return Encoding.UTF8.GetString(bytes.ToArray());
45
#endif
46
    }
3✔
47

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

64
        var writer = new Utf8JsonWriter(stream, options);
6✔
65

66
        writer.WriteStartArray();
6✔
67

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

70
        writer.WriteEndArray();
6✔
71

72
        writer.Flush();
6✔
73
    }
6✔
74

75

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

90
        using var stream = _memoryStreamManager.GetStream();
9✔
91

92
        await QueryJsonAsync(dataCommand, stream, options, cancellationToken);
9✔
93

94
        var bytes = stream.GetReadOnlySequence();
9✔
95

96
#if NET5_0_OR_GREATER
97
        return Encoding.UTF8.GetString(bytes);
9✔
98
#else
99
        return Encoding.UTF8.GetString(bytes.ToArray());
100
#endif
101

102
    }
9✔
103

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

121
        var writer = new Utf8JsonWriter(stream, options);
12✔
122

123
        writer.WriteStartArray();
12✔
124

125
        await dataCommand.ReadAsync(async (reader, token) =>
12✔
126
        {
12✔
127
            if (reader is DbDataReader dataReader)
12!
128
                await WriteDataAsync(dataReader, writer, token);
12✔
129
            else
12✔
130
                WriteData(reader, writer);
×
131

12✔
132
        }, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult, cancellationToken);
24✔
133

134
        writer.WriteEndArray();
12✔
135

136
        await writer.FlushAsync(cancellationToken);
12✔
137
    }
12✔
138

139

140
    private static void WriteData(IDataReader reader, Utf8JsonWriter writer)
141
    {
142
        while (reader.Read())
6,006✔
143
        {
144
            WriteObject(reader, writer);
6,000✔
145
        }
146
    }
6✔
147

148
    private static async Task WriteDataAsync(DbDataReader reader, Utf8JsonWriter writer, CancellationToken cancellationToken = default)
149
    {
150
        while (await reader.ReadAsync(cancellationToken))
6,033✔
151
        {
152
            WriteObject(reader, writer);
6,021✔
153
        }
154
    }
12✔
155

156
    private static void WriteObject(IDataReader reader, Utf8JsonWriter writer)
157
    {
158
        writer.WriteStartObject();
12,021✔
159

160
        for (int index = 0; index < reader.FieldCount; index++)
480,558✔
161
        {
162
            var name = reader.GetName(index);
228,258✔
163
            writer.WritePropertyName(name);
228,258✔
164

165
            WriteValue(reader, writer, index);
228,258✔
166
        }
167

168
        writer.WriteEndObject();
12,021✔
169
    }
12,021✔
170

171
    private static void WriteValue(IDataReader reader, Utf8JsonWriter writer, int index)
172
    {
173
        if (reader.IsDBNull(index))
228,258✔
174
        {
175
            writer.WriteNullValue();
72,232✔
176
            return;
72,232✔
177
        }
178

179
        var type = reader.GetFieldType(index);
156,026✔
180
        if (type == typeof(string))
156,026✔
181
        {
182
            var value = reader.GetString(index);
59,843✔
183
            writer.WriteStringValue(value);
59,843✔
184
            return;
59,843✔
185
        }
186

187
        if (type == typeof(bool))
96,183✔
188
        {
189
            var value = reader.GetBoolean(index);
36,024✔
190
            writer.WriteBooleanValue(value);
36,024✔
191
            return;
36,024✔
192
        }
193

194
        if (type == typeof(byte))
60,159!
195
        {
196
            var value = reader.GetByte(index);
×
197
            writer.WriteNumberValue(value);
×
198
            return;
×
199
        }
200

201
        if (type == typeof(short))
60,159✔
202
        {
203
            var value = reader.GetInt16(index);
6✔
204
            writer.WriteNumberValue(value);
6✔
205
            return;
6✔
206
        }
207

208
        if (type == typeof(int))
60,153✔
209
        {
210
            var value = reader.GetInt32(index);
12,036✔
211
            writer.WriteNumberValue(value);
12,036✔
212
            return;
12,036✔
213
        }
214

215
        if (type == typeof(long))
48,117✔
216
        {
217
            var value = reader.GetInt64(index);
9✔
218
            writer.WriteNumberValue(value);
9✔
219
            return;
9✔
220
        }
221

222
        if (type == typeof(float))
48,108✔
223
        {
224
            var value = reader.GetFloat(index);
6✔
225
            writer.WriteNumberValue(value);
6✔
226
            return;
6✔
227
        }
228

229
        if (type == typeof(double))
48,102✔
230
        {
231
            var value = reader.GetDouble(index);
6✔
232
            writer.WriteNumberValue(value);
6✔
233
            return;
6✔
234
        }
235

236
        if (type == typeof(decimal))
48,096✔
237
        {
238
            var value = reader.GetDecimal(index);
6✔
239
            writer.WriteNumberValue(value);
6✔
240
            return;
6✔
241
        }
242

243
#if NET6_0_OR_GREATER
244
        if (type == typeof(DateOnly))
48,090!
245
        {
246
            var value = reader.GetValue<DateOnly>(index);
×
247
            var formatted = value.ToString("yyyy'-'MM'-'dd", CultureInfo.InvariantCulture);
×
248

249
            writer.WriteStringValue(formatted);
×
250
            return;
×
251
        }
252

253
        if (type == typeof(TimeOnly))
48,090!
254
        {
255
            var value = reader.GetValue<TimeOnly>(index);
×
256
            string formatted = value.Second == 0 && value.Millisecond == 0
×
257
                ? value.ToString("HH':'mm", CultureInfo.InvariantCulture)
×
258
                : value.ToString("HH':'mm':'ss.FFFFFFF", CultureInfo.InvariantCulture);
×
259

260
            writer.WriteStringValue(formatted);
×
261
            return;
×
262
        }
263
#endif
264

265
        if (type == typeof(TimeSpan))
48,090✔
266
        {
267
            var value = reader.GetValue<TimeSpan>(index);
12✔
268
            string formatted = value.Seconds == 0 && value.Milliseconds == 0
12!
269
                ? value.ToString(@"hh\:mm", CultureInfo.InvariantCulture)
12✔
270
                : value.ToString();
12✔
271

272
            writer.WriteStringValue(formatted);
12✔
273
            return;
12✔
274
        }
275

276
        if (type == typeof(DateTime))
48,078✔
277
        {
278
            var value = reader.GetDateTime(index);
12✔
279
            var dataType = reader.GetDataTypeName(index).ToLowerInvariant();
12✔
280

281
            if (string.Equals(dataType, "date", StringComparison.OrdinalIgnoreCase))
12✔
282
            {
283
                var formattedDate = value.ToString("yyyy'-'MM'-'dd", CultureInfo.InvariantCulture);
6✔
284
                writer.WriteStringValue(formattedDate);
6✔
285
            }
286
            else
287
            {
288
                writer.WriteStringValue(value);
6✔
289
            }
290
            return;
6✔
291
        }
292

293
        if (type == typeof(DateTimeOffset))
48,066✔
294
        {
295
            var value = reader.GetValue(index);
24,042✔
296
            if (value is DateTimeOffset offset)
24,042!
297
            {
298
                writer.WriteStringValue(offset);
24,042✔
299
                return;
24,042✔
300
            }
301

302
            var date = reader.GetDateTime(index);
×
303
            date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
×
304

305
            offset = new DateTimeOffset(date, TimeSpan.Zero);
×
306

307
            writer.WriteStringValue(offset);
×
308
            return;
×
309
        }
310

311
        if (type == typeof(Guid))
24,024✔
312
        {
313
            var value = reader.GetGuid(index);
12,006✔
314
            writer.WriteStringValue(value);
12,006✔
315
            return;
12,006✔
316
        }
317

318
        // fallback
319
        var v = reader.GetValue(index);
12,018✔
320
        writer.WriteStringValue(v.ToString());
12,018✔
321
    }
12,018✔
322
}
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