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

loresoft / FluentCommand / 6648415992

26 Oct 2023 01:49AM UTC coverage: 51.645% (+0.1%) from 51.515%
6648415992

push

github

pwelter34
Update InsertBuilder.cs

981 of 2442 branches covered (0.0%)

Branch coverage included in aggregate %.

2896 of 5065 relevant lines covered (57.18%)

156.37 hits per line

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

61.54
/src/FluentCommand/Query/SelectEntityBuilder.cs
1
using System.Linq.Expressions;
2

3
using FluentCommand.Extensions;
4
using FluentCommand.Query.Generators;
5
using FluentCommand.Reflection;
6

7
namespace FluentCommand.Query;
8

9
/// <summary>
10
/// Select query builder
11
/// </summary>
12
/// <typeparam name="TEntity">The type of the entity.</typeparam>
13
public class SelectEntityBuilder<TEntity>
14
    : SelectBuilder<SelectEntityBuilder<TEntity>>, IWhereEntityBuilder<TEntity, SelectEntityBuilder<TEntity>>
15
    where TEntity : class
16
{
17
    private static readonly TypeAccessor _typeAccessor = TypeAccessor.GetAccessor<TEntity>();
10✔
18

19
    /// <summary>
20
    /// Initializes a new instance of the <see cref="SelectEntityBuilder{TEntity}"/> class.
21
    /// </summary>
22
    /// <param name="queryGenerator">The query generator.</param>
23
    /// <param name="parameters">The query parameters.</param>
24
    /// <param name="logicalOperator">The logical operator.</param>
25
    public SelectEntityBuilder(IQueryGenerator queryGenerator, List<QueryParameter> parameters, LogicalOperators logicalOperator = LogicalOperators.And)
26
        : base(queryGenerator, parameters, logicalOperator)
47✔
27
    {
28
    }
47✔
29

30
    /// <summary>
31
    /// Adds a column expression with the specified property.
32
    /// </summary>
33
    /// <param name="property">The property.</param>
34
    /// <param name="tableAlias">The table alias.</param>
35
    /// <param name="columnAlias">The column alias.</param>
36
    /// <returns></returns>
37
    public SelectEntityBuilder<TEntity> Column(
38
        Expression<Func<TEntity, object>> property,
39
        string tableAlias = null,
40
        string columnAlias = null)
41
    {
42
        var propertyAccessor = _typeAccessor.FindProperty(property);
26✔
43

44
        // alais column as property name if don't match
45
        if (propertyAccessor.Name == propertyAccessor.Column)
26✔
46
            return Column(propertyAccessor.Column, tableAlias, columnAlias);
25✔
47
        else
48
            return Column(propertyAccessor.Column, tableAlias, columnAlias ?? propertyAccessor.Name);
1✔
49

50
    }
51

52
    /// <summary>
53
    /// Adds a column expression with the specified property.
54
    /// </summary>
55
    /// <typeparam name="TModel">The type of the model.</typeparam>
56
    /// <param name="property">The property.</param>
57
    /// <param name="tableAlias">The table alias.</param>
58
    /// <param name="columnAlias">The column alias.</param>
59
    /// <returns></returns>
60
    public SelectEntityBuilder<TEntity> Column<TModel>(
61
        Expression<Func<TModel, object>> property,
62
        string tableAlias = null,
63
        string columnAlias = null) where TModel : class
64
    {
65
        var typeAccessor = TypeAccessor.GetAccessor<TModel>();
6✔
66
        var propertyAccessor = typeAccessor.FindProperty(property);
6✔
67

68
        // alais column as property name if don't match
69
        if (propertyAccessor.Name == propertyAccessor.Column)
6!
70
            return Column(propertyAccessor.Column, tableAlias, columnAlias);
6✔
71
        else
72
            return Column(propertyAccessor.Column, tableAlias, columnAlias ?? propertyAccessor.Name);
×
73

74
    }
75

76
    /// <summary>
77
    /// Conditionally adds a column expression with the specified property.
78
    /// </summary>
79
    /// <typeparam name="TValue">The type of the value.</typeparam>
80
    /// <param name="property">The property.</param>
81
    /// <param name="tableAlias">The table alias.</param>
82
    /// <param name="columnAlias">The column alias.</param>
83
    /// <param name="condition">The condition.</param>
84
    /// <returns></returns>
85
    public SelectEntityBuilder<TEntity> ColumnIf<TValue>(
86
        Expression<Func<TEntity, TValue>> property,
87
        string tableAlias = null,
88
        string columnAlias = null,
89
        Func<string, bool> condition = null)
90
    {
91
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
92

93
        // alais column as property name if don't match
94
        if (propertyAccessor.Name == propertyAccessor.Column)
×
95
            return ColumnIf(propertyAccessor.Column, tableAlias, columnAlias, condition);
×
96
        else
97
            return ColumnIf(propertyAccessor.Column, tableAlias, columnAlias ?? propertyAccessor.Name, condition);
×
98
    }
99

100
    /// <summary>
101
    /// Adds a column expression for each of specified names.
102
    /// </summary>
103
    /// <param name="columnNames">The column names.</param>
104
    /// <param name="tableAlias">The table alias.</param>
105
    /// <returns>
106
    /// The same builder so that multiple calls can be chained.
107
    /// </returns>
108
    /// <exception cref="System.ArgumentNullException">columnNames</exception>
109
    public override SelectEntityBuilder<TEntity> Columns(
110
        IEnumerable<string> columnNames,
111
        string tableAlias = null)
112
    {
113
        if (columnNames is null)
1!
114
            throw new ArgumentNullException(nameof(columnNames));
×
115

116
        foreach (var column in columnNames)
6✔
117
        {
118
            var propertyAccessor = _typeAccessor.FindColumn(column);
2✔
119
            if (propertyAccessor is null)
2✔
120
                continue;
121

122
            // alias column as property name if don't match
123
            if (propertyAccessor.Name == propertyAccessor.Column)
2✔
124
                Column(propertyAccessor.Column, tableAlias);
1✔
125
            else
126
                Column(propertyAccessor.Column, tableAlias, propertyAccessor.Name);
1✔
127
        }
128

129
        return this;
1✔
130
    }
131

132
    /// <summary>
133
    /// Adds a column expression for each property in <typeparamref name="TEntity" />.
134
    /// </summary>
135
    /// <param name="tableAlias">The table alias.</param>
136
    /// <param name="filter">An optional filter to include properties.</param>
137
    /// <returns>
138
    /// The same builder so that multiple calls can be chained.
139
    /// </returns>
140
    public SelectEntityBuilder<TEntity> Columns(
141
        string tableAlias = null,
142
        Func<IMemberAccessor, bool> filter = null)
143
    {
144
        var properties = _typeAccessor.GetProperties();
3✔
145

146
        foreach (var property in properties)
144✔
147
        {
148
            if (property.IsNotMapped)
69✔
149
                continue;
150

151
            if (filter != null && !filter(property))
57✔
152
                continue;
153

154
            // alias column as property name if don't match
155
            if (property.Name == property.Column)
56!
156
                Column(property.Column, tableAlias);
56✔
157
            else
158
                Column(property.Column, tableAlias, property.Name);
×
159
        }
160

161
        return this;
3✔
162
    }
163

164
    /// <summary>
165
    /// Adds a column expression for each property in <typeparamref name="TModel" />.
166
    /// </summary>
167
    /// <typeparam name="TModel">The type of the model.</typeparam>
168
    /// <param name="tableAlias">The table alias.</param>
169
    /// <param name="filter">An optional filter to include properties.</param>
170
    /// <returns>
171
    /// The same builder so that multiple calls can be chained.
172
    /// </returns>
173
    public SelectEntityBuilder<TEntity> Columns<TModel>(
174
        string tableAlias = null,
175
        Func<IMemberAccessor, bool> filter = null)
176
    {
177
        var typeAccessor = TypeAccessor.GetAccessor(typeof(TModel));
×
178
        var properties = typeAccessor.GetProperties();
×
179

180
        foreach (var property in properties)
×
181
        {
182
            if (property.IsNotMapped)
×
183
                continue;
184

185
            if (filter != null && !filter(property))
×
186
                continue;
187

188
            // alias column as property name if don't match
189
            if (property.Name == property.Column)
×
190
                Column(property.Column, tableAlias);
×
191
            else
192
                Column(property.Column, tableAlias, property.Name);
×
193
        }
194

195
        return this;
×
196
    }
197

198
    /// <summary>
199
    /// Adds a count expression using the specified property.
200
    /// </summary>
201
    /// <typeparam name="TValue">The type of the value.</typeparam>
202
    /// <param name="property">The property.</param>
203
    /// <param name="tableAlias">The table alias.</param>
204
    /// <param name="columnAlias">The column alias.</param>
205
    /// <returns>
206
    /// The same builder so that multiple calls can be chained.
207
    /// </returns>
208
    public SelectEntityBuilder<TEntity> Count<TValue>(
209
        Expression<Func<TEntity, TValue>> property,
210
        string tableAlias = null,
211
        string columnAlias = null)
212
    {
213
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
214

215
        return Count(propertyAccessor.Column, tableAlias, columnAlias);
×
216
    }
217

218
    /// <summary>
219
    /// Adds an aggregate expression using the specified function and property.
220
    /// </summary>
221
    /// <typeparam name="TValue">The type of the value.</typeparam>
222
    /// <param name="property">The property.</param>
223
    /// <param name="function">The aggregate function.</param>
224
    /// <param name="tableAlias">The table alias.</param>
225
    /// <param name="columnAlias">The column alias.</param>
226
    /// <returns>
227
    /// The same builder so that multiple calls can be chained.
228
    /// </returns>
229
    public SelectEntityBuilder<TEntity> Aggregate<TValue>(
230
        Expression<Func<TEntity, TValue>> property,
231
        AggregateFunctions function,
232
        string tableAlias = null,
233
        string columnAlias = null)
234
    {
235
        var propertyAccessor = _typeAccessor.FindProperty(property);
3✔
236

237
        return Aggregate(function, propertyAccessor.Column, tableAlias, columnAlias);
3✔
238
    }
239

240
    /// <inheritdoc />
241
    public override SelectEntityBuilder<TEntity> From(
242
        string tableName = null,
243
        string tableSchema = null,
244
        string tableAlias = null)
245
    {
246
        return base.From(
44✔
247
            tableName ?? _typeAccessor.TableName,
44✔
248
            tableSchema ?? _typeAccessor.TableSchema,
44✔
249
            tableAlias);
44✔
250
    }
251

252
    /// <summary>
253
    /// Add a join clause using the specified builder action
254
    /// </summary>
255
    /// <typeparam name="TRight">The right join entity</typeparam>
256
    /// <param name="builder">The join builder.</param>
257
    /// <returns>
258
    /// The same builder so that multiple calls can be chained.
259
    /// </returns>
260
    public SelectEntityBuilder<TEntity> Join<TRight>(Action<JoinEntityBuilder<TEntity, TRight>> builder)
261
        where TRight : class
262
    {
263
        var innerBuilder = new JoinEntityBuilder<TEntity, TRight>(QueryGenerator, Parameters);
7✔
264
        builder(innerBuilder);
7✔
265

266
        JoinExpressions.Add(innerBuilder.BuildExpression());
7✔
267

268
        return this;
7✔
269
    }
270

271
    /// <summary>
272
    /// Add a join clause using the specified builder action
273
    /// </summary>
274
    /// <typeparam name="TLeft">The left join entity</typeparam>
275
    /// <typeparam name="TRight">The right join entity</typeparam>
276
    /// <param name="builder">The join builder.</param>
277
    /// <returns>
278
    /// The same builder so that multiple calls can be chained.
279
    /// </returns>
280
    public SelectEntityBuilder<TEntity> Join<TLeft, TRight>(Action<JoinEntityBuilder<TLeft, TRight>> builder)
281
        where TLeft : class
282
        where TRight : class
283
    {
284
        var innerBuilder = new JoinEntityBuilder<TLeft, TRight>(QueryGenerator, Parameters);
3✔
285
        builder(innerBuilder);
3✔
286

287
        JoinExpressions.Add(innerBuilder.BuildExpression());
3✔
288

289
        return this;
3✔
290
    }
291

292
    /// <inheritdoc />
293
    public SelectEntityBuilder<TEntity> Where<TValue>(
294
        Expression<Func<TEntity, TValue>> property,
295
        TValue parameterValue,
296
        FilterOperators filterOperator = FilterOperators.Equal)
297
    {
298
        return Where<TValue>(property, parameterValue, null, filterOperator);
20✔
299
    }
300

301
    /// <inheritdoc />
302
    public SelectEntityBuilder<TEntity> Where<TValue>(
303
        Expression<Func<TEntity, TValue>> property,
304
        TValue parameterValue,
305
        string tableAlias,
306
        FilterOperators filterOperator = FilterOperators.Equal)
307
    {
308
        var propertyAccessor = _typeAccessor.FindProperty(property);
24✔
309

310
        return Where(propertyAccessor.Column, parameterValue, tableAlias, filterOperator);
24✔
311
    }
312

313
    /// <summary>
314
    /// Create a where clause with the specified property, value, operator and table alias
315
    /// </summary>
316
    /// <typeparam name="TModel">The type of the model</typeparam>
317
    /// <typeparam name="TValue">The type of the value.</typeparam>
318
    /// <param name="property">The property.</param>
319
    /// <param name="parameterValue">The parameter value.</param>
320
    /// <param name="tableAlias">The table alias.</param>
321
    /// <param name="filterOperator">The filter operator.</param>
322
    /// <returns>
323
    /// The same builder so that multiple calls can be chained.
324
    /// </returns>
325
    public SelectEntityBuilder<TEntity> Where<TModel, TValue>(
326
        Expression<Func<TModel, TValue>> property,
327
        TValue parameterValue,
328
        string tableAlias,
329
        FilterOperators filterOperator = FilterOperators.Equal)
330
    {
331
        var typeAccessor = TypeAccessor.GetAccessor<TModel>();
1✔
332
        var propertyAccessor = typeAccessor.FindProperty(property);
1✔
333

334
        return Where(propertyAccessor.Column, parameterValue, tableAlias, filterOperator);
1✔
335
    }
336

337
    /// <inheritdoc />
338
    public SelectEntityBuilder<TEntity> WhereIf<TValue>(
339
        Expression<Func<TEntity, TValue>> property,
340
        TValue parameterValue,
341
        FilterOperators filterOperator = FilterOperators.Equal,
342
        Func<string, TValue, bool> condition = null)
343
    {
344
        return WhereIf(property, parameterValue, null, filterOperator, condition);
×
345
    }
346

347
    /// <inheritdoc />
348
    public SelectEntityBuilder<TEntity> WhereIf<TValue>(
349
        Expression<Func<TEntity, TValue>> property,
350
        TValue parameterValue,
351
        string tableAlias,
352
        FilterOperators filterOperator = FilterOperators.Equal,
353
        Func<string, TValue, bool> condition = null)
354
    {
355
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
356

357
        return WhereIf(propertyAccessor.Column, parameterValue, tableAlias, filterOperator, condition);
×
358
    }
359

360
    /// <inheritdoc />
361
    public SelectEntityBuilder<TEntity> WhereIn<TValue>(
362
        Expression<Func<TEntity, TValue>> property,
363
        IEnumerable<TValue> parameterValues,
364
        string tableAlias = null)
365
    {
366
        var propertyAccessor = _typeAccessor.FindProperty(property);
8✔
367

368
        return WhereIn(propertyAccessor?.Column, parameterValues, tableAlias);
8!
369
    }
370

371
    /// <inheritdoc />
372
    public SelectEntityBuilder<TEntity> WhereInIf<TValue>(
373
        Expression<Func<TEntity, TValue>> property,
374
        IEnumerable<TValue> parameterValues,
375
        Func<string, IEnumerable<TValue>, bool> condition = null)
376
    {
377
        var propertyAccessor = _typeAccessor.FindProperty(property);
1✔
378

379
        return WhereInIf(propertyAccessor?.Column, parameterValues, condition);
1!
380
    }
381

382
    /// <inheritdoc />
383
    public SelectEntityBuilder<TEntity> WhereInIf<TValue>(
384
        Expression<Func<TEntity, TValue>> property,
385
        IEnumerable<TValue> parameterValues,
386
        string tableAlias,
387
        Func<string, IEnumerable<TValue>, bool> condition = null)
388
    {
389
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
390

391
        return WhereInIf(propertyAccessor?.Column, parameterValues, tableAlias, condition);
×
392
    }
393

394
    /// <inheritdoc />
395
    public SelectEntityBuilder<TEntity> WhereOr(Action<LogicalEntityBuilder<TEntity>> builder)
396
    {
397
        var innerBuilder = new LogicalEntityBuilder<TEntity>(QueryGenerator, Parameters, LogicalOperators.Or);
5✔
398

399
        builder(innerBuilder);
5✔
400

401
        var statement = innerBuilder.BuildStatement();
5✔
402

403
        if (statement != null)
5✔
404
            WhereExpressions.Add(new WhereExpression(statement.Statement, IsRaw: true));
5✔
405

406
        return this;
5✔
407
    }
408

409
    /// <inheritdoc />
410
    public SelectEntityBuilder<TEntity> WhereAnd(Action<LogicalEntityBuilder<TEntity>> builder)
411
    {
412
        var innerBuilder = new LogicalEntityBuilder<TEntity>(QueryGenerator, Parameters, LogicalOperators.And);
×
413

414
        builder(innerBuilder);
×
415

416
        var statement = innerBuilder.BuildStatement();
×
417

418
        if (statement != null && statement.Statement.HasValue())
×
419
            WhereExpressions.Add(new WhereExpression(statement.Statement, IsRaw: true));
×
420

421
        return this;
×
422
    }
423

424

425
    /// <summary>
426
    /// Add an order by clause with the specified property and sort direction.
427
    /// </summary>
428
    /// <typeparam name="TValue">The type of the value.</typeparam>
429
    /// <param name="property">The property.</param>
430
    /// <param name="sortDirection">The sort direction.</param>
431
    /// <returns>
432
    /// The same builder so that multiple calls can be chained.
433
    /// </returns>
434
    public SelectEntityBuilder<TEntity> OrderBy<TValue>(
435
        Expression<Func<TEntity, TValue>> property,
436
        SortDirections sortDirection = SortDirections.Ascending)
437
    {
438
        var propertyAccessor = _typeAccessor.FindProperty(property);
21✔
439

440
        return OrderBy(propertyAccessor.Column, null, sortDirection);
21✔
441
    }
442

443
    /// <summary>
444
    /// Add an order by clause with the specified property, sort direction and table alias.
445
    /// </summary>
446
    /// <typeparam name="TValue">The type of the value.</typeparam>
447
    /// <param name="property">The property.</param>
448
    /// <param name="tableAlias">The table alias.</param>
449
    /// <param name="sortDirection">The sort direction.</param>
450
    /// <returns>
451
    /// The same builder so that multiple calls can be chained.
452
    /// </returns>
453
    public SelectEntityBuilder<TEntity> OrderBy<TValue>(
454
        Expression<Func<TEntity, TValue>> property,
455
        string tableAlias,
456
        SortDirections sortDirection = SortDirections.Ascending)
457
    {
458
        var propertyAccessor = _typeAccessor.FindProperty(property);
4✔
459

460
        return OrderBy(propertyAccessor.Column, tableAlias, sortDirection);
4✔
461
    }
462

463
    /// <summary>
464
    /// Conditionally add an order by clause with the specified property and sort direction.
465
    /// </summary>
466
    /// <typeparam name="TValue">The type of the value.</typeparam>
467
    /// <param name="property">The property.</param>
468
    /// <param name="sortDirection">The sort direction.</param>
469
    /// <param name="condition">The condition.</param>
470
    /// <returns>
471
    /// The same builder so that multiple calls can be chained.
472
    /// </returns>
473
    public SelectEntityBuilder<TEntity> OrderByIf<TValue>(
474
        Expression<Func<TEntity, TValue>> property,
475
        SortDirections sortDirection = SortDirections.Ascending,
476
        Func<string, bool> condition = null)
477
    {
478
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
479

480
        return OrderByIf(propertyAccessor.Column, null, sortDirection, condition);
×
481
    }
482

483
    /// <summary>
484
    /// Conditionally add an order by clause with the specified property, sort direction and table alias.
485
    /// </summary>
486
    /// <typeparam name="TValue">The type of the value.</typeparam>
487
    /// <param name="property">The property.</param>
488
    /// <param name="tableAlias">The table alias.</param>
489
    /// <param name="sortDirection">The sort direction.</param>
490
    /// <param name="condition">The condition.</param>
491
    /// <returns>
492
    /// The same builder so that multiple calls can be chained.
493
    /// </returns>
494
    public SelectEntityBuilder<TEntity> OrderByIf<TValue>(
495
        Expression<Func<TEntity, TValue>> property,
496
        string tableAlias,
497
        SortDirections sortDirection = SortDirections.Ascending,
498
        Func<string, bool> condition = null)
499
    {
500
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
501

502
        return OrderByIf(propertyAccessor.Column, tableAlias, sortDirection, condition);
×
503
    }
504

505
    /// <summary>
506
    /// Add a group by clause with the specified property  and table alias.
507
    /// </summary>
508
    /// <typeparam name="TValue">The type of the value.</typeparam>
509
    /// <param name="property">The property.</param>
510
    /// <param name="tableAlias">The table alias.</param>
511
    /// <returns>
512
    /// The same builder so that multiple calls can be chained.
513
    /// </returns>
514
    public SelectEntityBuilder<TEntity> GroupBy<TValue>(
515
        Expression<Func<TEntity, TValue>> property,
516
        string tableAlias = null)
517
    {
518
        var propertyAccessor = _typeAccessor.FindProperty(property);
3✔
519

520
        return GroupBy(propertyAccessor.Column, tableAlias);
3✔
521
    }
522

523
    /// <inheritdoc />
524
    public override QueryStatement BuildStatement()
525
    {
526
        // add table and schema from attribute if not set
527
        if (FromExpressions.Count == 0)
47✔
528
            From(_typeAccessor.TableName, _typeAccessor.TableSchema);
39✔
529

530
        return base.BuildStatement();
47✔
531
    }
532

533

534

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