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

loresoft / FluentCommand / 15638433985

13 Jun 2025 03:39PM UTC coverage: 54.709% (+0.5%) from 54.174%
15638433985

push

github

pwelter34
misc updates

1692 of 3584 branches covered (47.21%)

Branch coverage included in aggregate %.

114 of 156 new or added lines in 9 files covered. (73.08%)

15 existing lines in 5 files now uncovered.

4291 of 7352 relevant lines covered (58.37%)

233.09 hits per line

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

71.88
/src/FluentCommand/ListDataReader.cs
1
using System.Data;
2

3
using FluentCommand.Extensions;
4
using FluentCommand.Reflection;
5

6
namespace FluentCommand;
7

8
/// <summary>
9
/// Read a list of items using an <see cref="IDataReader"/>
10
/// </summary>
11
/// <typeparam name="T">The type of items being read</typeparam>
12
public class ListDataReader<T> : IDataReader where T : class
13
{
14
    // ReSharper disable once StaticMemberInGenericType
15
    private static readonly TypeAccessor _typeAccessor;
16

17
    private readonly IEnumerator<T> _iterator;
18
    private readonly List<IMemberAccessor> _activeColumns;
19
    private readonly Dictionary<string, int> _columnOrdinals;
20
    private bool _disposed;
21

22
    static ListDataReader()
23
    {
24
        _typeAccessor = TypeAccessor.GetAccessor<T>();
5✔
25
    }
5✔
26

27
    /// <summary>
28
    /// Initializes a new instance of the <see cref="ListDataReader{T}"/> class.
29
    /// </summary>
30
    /// <param name="list">The list of items to read</param>
31
    /// <param name="ignoreNames">A list of property names to ignore in the reader</param>
32
    public ListDataReader(IEnumerable<T> list, IEnumerable<string> ignoreNames = null)
29✔
33
    {
34
        if (list is null)
29✔
35
            throw new ArgumentNullException(nameof(list));
1✔
36

37
        _iterator = list.GetEnumerator();
28✔
38

39
        var ignored = new HashSet<string>(ignoreNames ?? Enumerable.Empty<string>());
28✔
40

41
        _activeColumns = _typeAccessor
28✔
42
            .GetProperties()
28✔
43
            .Where(c => !ignored.Contains(c.Name))
199✔
44
            .ToList();
28✔
45

46
        _columnOrdinals = _activeColumns
28✔
47
            .Select((col, idx) => new { col.Column, idx })
196✔
48
            .ToDictionary(x => x.Column, x => x.idx, StringComparer.OrdinalIgnoreCase);
420✔
49
    }
28✔
50

51
    /// <summary>
52
    /// Gets a value indicating the depth of nesting for the current row. Always returns 0.
53
    /// </summary>
UNCOV
54
    public int Depth => 0;
×
55

56
    /// <summary>
57
    /// Gets a value indicating whether the data reader is closed.
58
    /// </summary>
59
    public bool IsClosed { get; private set; }
53✔
60

61
    /// <summary>
62
    /// Gets the number of rows affected. Always returns 0.
63
    /// </summary>
UNCOV
64
    public int RecordsAffected => 0;
×
65

66
    /// <summary>
67
    /// Closes the data reader and releases resources.
68
    /// </summary>
69
    public void Close()
70
    {
71
        Dispose(true);
2✔
72
    }
2✔
73

74
    /// <summary>
75
    /// Returns a <see cref="DataTable"/> that describes the column metadata of the data reader.
76
    /// </summary>
77
    /// <returns>A <see cref="DataTable"/> describing the column metadata.</returns>
78
    public DataTable GetSchemaTable()
79
    {
80
        // these are the columns used by DataTable load
81
        var table = new DataTable
3✔
82
        {
3✔
83
            Columns =
3✔
84
            {
3✔
85
                {"ColumnOrdinal", typeof(int)},
3✔
86
                {"ColumnName", typeof(string)},
3✔
87
                {"DataType", typeof(Type)},
3✔
88
                {"ColumnSize", typeof(int)},
3✔
89
                {"AllowDBNull", typeof(bool)}
3✔
90
            }
3✔
91
        };
3✔
92

93
        for (int i = 0; i < _activeColumns.Count; i++)
28✔
94
        {
95
            var rowData = new object[5];
11✔
96
            rowData[0] = i;
11✔
97
            rowData[1] = _activeColumns[i].Column;
11✔
98
            rowData[2] = _activeColumns[i].MemberType.GetUnderlyingType();
11✔
99
            rowData[3] = -1;
11✔
100
            rowData[4] = _activeColumns[i].MemberType.IsNullable();
11✔
101

102
            table.Rows.Add(rowData);
11✔
103
        }
104

105
        return table;
3✔
106
    }
107

108
    /// <summary>
109
    /// Advances the data reader to the next result. Always returns false.
110
    /// </summary>
111
    /// <returns>false, as multiple result sets are not supported.</returns>
112
    public bool NextResult() => false;
2✔
113

114
    /// <summary>
115
    /// Advances the data reader to the next record.
116
    /// </summary>
117
    /// <returns>true if there are more rows; otherwise, false.</returns>
118
    public bool Read() => _iterator.MoveNext();
1,137✔
119

120
    /// <summary>
121
    /// Releases all resources used by the <see cref="ListDataReader{T}"/>.
122
    /// </summary>
123
    public void Dispose()
124
    {
125
        Dispose(true);
23✔
126
        GC.SuppressFinalize(this);
23✔
127
    }
23✔
128

129
    /// <summary>
130
    /// Releases the unmanaged resources used by the ListDataReader and optionally releases the managed resources.
131
    /// </summary>
132
    /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
133
    protected virtual void Dispose(bool disposing)
134
    {
135
        if (_disposed)
25✔
136
            return;
1✔
137

138
        if (disposing)
24✔
139
        {
140
            if (!IsClosed)
24✔
141
            {
142
                _iterator.Dispose();
24✔
143
                IsClosed = true;
24✔
144
            }
145
        }
146

147
        _disposed = true;
24✔
148
    }
24✔
149

150
    /// <inheritdoc/>
151
    public string GetName(int i) => _activeColumns[i].Column;
2,526✔
152

153
    /// <inheritdoc/>
154
    public string GetDataTypeName(int i) => _activeColumns[i].MemberType.Name;
×
155

156
    /// <inheritdoc/>
157
    public Type GetFieldType(int i) => _activeColumns[i].MemberType;
2,497✔
158

159
    /// <inheritdoc/>
160
    public object GetValue(int i) => _activeColumns[i].GetValue(_iterator.Current);
9,915✔
161

162
    /// <inheritdoc/>
163
    public int GetValues(object[] values)
164
    {
165
        int count = Math.Min(_activeColumns.Count, values.Length);
102✔
166
        for (int i = 0; i < count; i++)
1,412✔
167
            values[i] = GetValue(i);
604✔
168
        return count;
102✔
169
    }
170

171
    /// <inheritdoc/>
172
    public int GetOrdinal(string name)
173
    {
174
        if (_columnOrdinals.TryGetValue(name, out int ordinal))
84✔
175
            return ordinal;
81✔
176

177
        return -1;
3✔
178
    }
179

180
    /// <inheritdoc/>
181
    public bool GetBoolean(int i) => (bool)GetValue(i);
×
182

183
    /// <inheritdoc/>
184
    public byte GetByte(int i) => (byte)GetValue(i);
×
185

186
    /// <inheritdoc/>
187
    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferOffset, int length)
188
    {
189
        byte[] value = (byte[])GetValue(i);
×
190

191
        int available = value.Length - (int)fieldOffset;
×
192
        if (available <= 0)
×
193
            return 0;
×
194

195
        int count = Math.Min(length, available);
×
196

NEW
197
        Buffer.BlockCopy(value, (int)fieldOffset, buffer, bufferOffset, count);
×
198

199
        return count;
×
200
    }
201

202
    /// <inheritdoc/>
203
    public char GetChar(int i) => (char)GetValue(i);
×
204

205
    /// <inheritdoc/>
206
    public long GetChars(int i, long fieldOffset, char[] buffer, int bufferOffset, int length)
207
    {
208
        if (buffer == null)
×
209
            throw new ArgumentNullException(nameof(buffer));
×
210

211
        string value = (string)GetValue(i);
×
212

NEW
213
        int available = value.Length - (int)fieldOffset;
×
214
        if (available <= 0)
×
215
            return 0;
×
216

217
        int count = Math.Min(length, available);
×
218

NEW
219
        value.CopyTo((int)fieldOffset, buffer, bufferOffset, count);
×
220

221
        return count;
×
222
    }
223

224
    /// <inheritdoc/>
225
    public Guid GetGuid(int i) => (Guid)GetValue(i);
×
226

227
    /// <inheritdoc/>
228
    public short GetInt16(int i) => (short)GetValue(i);
×
229

230
    /// <inheritdoc/>
231
    public int GetInt32(int i) => (int)GetValue(i);
4✔
232

233
    /// <inheritdoc/>
234
    public long GetInt64(int i) => (long)GetValue(i);
×
235

236
    /// <inheritdoc/>
237
    public float GetFloat(int i) => (float)GetValue(i);
×
238

239
    /// <inheritdoc/>
240
    public double GetDouble(int i) => (double)GetValue(i);
×
241

242
    /// <inheritdoc/>
243
    public string GetString(int i) => (string)GetValue(i);
4✔
244

245
    /// <inheritdoc/>
246
    public decimal GetDecimal(int i) => (decimal)GetValue(i);
×
247

248
    /// <inheritdoc/>
249
    public DateTime GetDateTime(int i) => (DateTime)GetValue(i);
2✔
250

251
    /// <inheritdoc/>
252
    public IDataReader GetData(int i) => throw new NotImplementedException();
1✔
253

254
    /// <inheritdoc/>
255
    public bool IsDBNull(int i)
256
    {
257
        var value = GetValue(i);
1✔
258
        return value == null || value == DBNull.Value;
1!
259
    }
260

261
    /// <inheritdoc/>
262
    public int FieldCount => _activeColumns.Count;
2,940✔
263

264
    /// <inheritdoc/>
265
    public object this[int i] => GetValue(i);
×
266

267
    /// <inheritdoc/>
268
    public object this[string name] => GetValue(GetOrdinal(name));
2✔
269
}
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