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

loresoft / FluentCommand / 23278216331

19 Mar 2026 03:19AM UTC coverage: 57.398% (+0.7%) from 56.658%
23278216331

push

github

pwelter34
Enable nullable and improve source generators

1403 of 3069 branches covered (45.72%)

Branch coverage included in aggregate %.

527 of 907 new or added lines in 58 files covered. (58.1%)

22 existing lines in 10 files now uncovered.

4288 of 6846 relevant lines covered (62.64%)

330.58 hits per line

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

0.0
/src/FluentCommand/Query/WhereEntityBuilder.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
/// Provides a builder for constructing SQL WHERE clauses for a specific entity type.
11
/// </summary>
12
/// <typeparam name="TEntity">The type of the entity.</typeparam>
13
public class WhereEntityBuilder<TEntity>
14
    : WhereBuilder<WhereEntityBuilder<TEntity>>, IWhereEntityBuilder<TEntity, WhereEntityBuilder<TEntity>>
15
    where TEntity : class
16
{
17
    private static readonly TypeAccessor _typeAccessor = TypeAccessor.GetAccessor<TEntity>();
×
18

19
    /// <summary>
20
    /// Initializes a new instance of the <see cref="WhereEntityBuilder{TEntity}"/> class.
21
    /// </summary>
22
    /// <param name="queryGenerator">The query generator used to build SQL statements.</param>
23
    /// <param name="parameters">The collection of query parameters.</param>
24
    /// <param name="logicalOperator">The logical operator to combine WHERE expressions (default is <see cref="LogicalOperators.And"/>).</param>
25
    public WhereEntityBuilder(
26
        IQueryGenerator queryGenerator,
27
        List<QueryParameter> parameters,
28
        LogicalOperators logicalOperator = LogicalOperators.And)
29
        : base(queryGenerator, parameters, logicalOperator)
×
30
    {
31
    }
×
32

33
    /// <summary>
34
    /// Adds a WHERE clause for the specified property, value, and filter operator.
35
    /// </summary>
36
    /// <typeparam name="TValue">The type of the value to compare.</typeparam>
37
    /// <param name="property">An expression selecting the property to filter on.</param>
38
    /// <param name="parameterValue">The value to compare the property against.</param>
39
    /// <param name="filterOperator">The filter operator to use (default is <see cref="FilterOperators.Equal"/>).</param>
40
    /// <returns>The builder instance for chaining further calls.</returns>
41
    public WhereEntityBuilder<TEntity> Where<TValue>(
42
        Expression<Func<TEntity, TValue>> property,
43
        TValue? parameterValue,
44
        FilterOperators filterOperator = FilterOperators.Equal)
45
    {
46
        return Where(property, parameterValue, null, filterOperator);
×
47
    }
48

49
    /// <summary>
50
    /// Adds a WHERE clause for the specified property, value, filter operator, and table alias.
51
    /// </summary>
52
    /// <typeparam name="TValue">The type of the value to compare.</typeparam>
53
    /// <param name="property">An expression selecting the property to filter on.</param>
54
    /// <param name="parameterValue">The value to compare the property against.</param>
55
    /// <param name="tableAlias">The table alias to use in the query.</param>
56
    /// <param name="filterOperator">The filter operator to use (default is <see cref="FilterOperators.Equal"/>).</param>
57
    /// <returns>The builder instance for chaining further calls.</returns>
58
    public WhereEntityBuilder<TEntity> Where<TValue>(
59
        Expression<Func<TEntity, TValue>> property,
60
        TValue? parameterValue,
61
        string? tableAlias,
62
        FilterOperators filterOperator = FilterOperators.Equal)
63
    {
NEW
64
        var propertyAccessor = GetPropertyAccessor(property);
×
65

NEW
66
        return Where(propertyAccessor.Column, parameterValue, tableAlias, filterOperator);
×
67
    }
68

69
    /// <summary>
70
    /// Adds a WHERE IN clause for the specified property and collection of values, with an optional table alias.
71
    /// </summary>
72
    /// <typeparam name="TValue">The type of the values to compare.</typeparam>
73
    /// <param name="property">An expression selecting the property to filter on.</param>
74
    /// <param name="parameterValues">The collection of values for the IN clause.</param>
75
    /// <param name="tableAlias">The table alias to use in the query (optional).</param>
76
    /// <returns>The builder instance for chaining further calls.</returns>
77
    public WhereEntityBuilder<TEntity> WhereIn<TValue>(
78
        Expression<Func<TEntity, TValue>> property,
79
        IEnumerable<TValue> parameterValues,
80
        string? tableAlias = null)
81
    {
NEW
82
        var propertyAccessor = GetPropertyAccessor(property);
×
83

NEW
84
        return WhereIn(propertyAccessor.Column, parameterValues, tableAlias);
×
85
    }
86

87
    /// <summary>
88
    /// Conditionally adds a WHERE IN clause for the specified property and collection of values.
89
    /// </summary>
90
    /// <typeparam name="TValue">The type of the values to compare.</typeparam>
91
    /// <param name="property">An expression selecting the property to filter on.</param>
92
    /// <param name="parameterValues">The collection of values for the IN clause.</param>
93
    /// <param name="condition">
94
    /// A function that determines whether to add the clause, based on the property name and values.
95
    /// If <c>null</c>, the clause is always added.
96
    /// </param>
97
    /// <returns>The builder instance for chaining further calls.</returns>
98
    public WhereEntityBuilder<TEntity> WhereInIf<TValue>(
99
        Expression<Func<TEntity, TValue>> property,
100
        IEnumerable<TValue> parameterValues,
101
        Func<string, IEnumerable<TValue>, bool>? condition = null)
102
    {
NEW
103
        var propertyAccessor = GetPropertyAccessor(property);
×
104

NEW
105
        return WhereInIf(propertyAccessor.Column, parameterValues, condition);
×
106
    }
107

108
    /// <summary>
109
    /// Conditionally adds a WHERE IN clause for the specified property, collection of values, and table alias.
110
    /// </summary>
111
    /// <typeparam name="TValue">The type of the values to compare.</typeparam>
112
    /// <param name="property">An expression selecting the property to filter on.</param>
113
    /// <param name="parameterValues">The collection of values for the IN clause.</param>
114
    /// <param name="tableAlias">The table alias to use in the query.</param>
115
    /// <param name="condition">
116
    /// A function that determines whether to add the clause, based on the table alias and values.
117
    /// If <c>null</c>, the clause is always added.
118
    /// </param>
119
    /// <returns>The builder instance for chaining further calls.</returns>
120
    public WhereEntityBuilder<TEntity> WhereInIf<TValue>(
121
        Expression<Func<TEntity, TValue>> property,
122
        IEnumerable<TValue> parameterValues,
123
        string? tableAlias,
124
        Func<string, IEnumerable<TValue>, bool>? condition = null)
125
    {
NEW
126
        var propertyAccessor = GetPropertyAccessor(property);
×
127

NEW
128
        return WhereInIf(propertyAccessor.Column, parameterValues, tableAlias, condition);
×
129
    }
130

131
    /// <summary>
132
    /// Conditionally adds a WHERE clause for the specified property, value, and filter operator.
133
    /// </summary>
134
    /// <typeparam name="TValue">The type of the value to compare.</typeparam>
135
    /// <param name="property">An expression selecting the property to filter on.</param>
136
    /// <param name="parameterValue">The value to compare the property against.</param>
137
    /// <param name="filterOperator">The filter operator to use (default is <see cref="FilterOperators.Equal"/>).</param>
138
    /// <param name="condition">
139
    /// A function that determines whether to add the clause, based on the property name and value.
140
    /// If <c>null</c>, the clause is always added.
141
    /// </param>
142
    /// <returns>The builder instance for chaining further calls.</returns>
143
    public WhereEntityBuilder<TEntity> WhereIf<TValue>(
144
        Expression<Func<TEntity, TValue>> property,
145
        TValue? parameterValue,
146
        FilterOperators filterOperator = FilterOperators.Equal,
147
        Func<string, TValue?, bool>? condition = null)
148
    {
149
        return WhereIf(property, parameterValue, null, filterOperator, condition);
×
150
    }
151

152
    /// <summary>
153
    /// Conditionally adds a WHERE clause for the specified property, value, filter operator, and table alias.
154
    /// </summary>
155
    /// <typeparam name="TValue">The type of the value to compare.</typeparam>
156
    /// <param name="property">An expression selecting the property to filter on.</param>
157
    /// <param name="parameterValue">The value to compare the property against.</param>
158
    /// <param name="tableAlias">The table alias to use in the query.</param>
159
    /// <param name="filterOperator">The filter operator to use (default is <see cref="FilterOperators.Equal"/>).</param>
160
    /// <param name="condition">
161
    /// A function that determines whether to add the clause, based on the table alias and value.
162
    /// If <c>null</c>, the clause is always added.
163
    /// </param>
164
    /// <returns>The builder instance for chaining further calls.</returns>
165
    public WhereEntityBuilder<TEntity> WhereIf<TValue>(
166
        Expression<Func<TEntity, TValue>> property,
167
        TValue? parameterValue,
168
        string? tableAlias,
169
        FilterOperators filterOperator = FilterOperators.Equal,
170
        Func<string, TValue?, bool>? condition = null)
171
    {
NEW
172
        var propertyAccessor = GetPropertyAccessor(property);
×
173

NEW
174
        return WhereIf(propertyAccessor.Column, parameterValue, tableAlias, filterOperator, condition);
×
175
    }
176

177
    /// <summary>
178
    /// Adds a logical OR group to the WHERE clause using the specified builder action.
179
    /// </summary>
180
    /// <param name="builder">An action that configures the logical OR group using a <see cref="LogicalEntityBuilder{TEntity}"/>.</param>
181
    /// <returns>The builder instance for chaining further calls.</returns>
182
    public WhereEntityBuilder<TEntity> WhereOr(Action<LogicalEntityBuilder<TEntity>> builder)
183
    {
184
        var innerBuilder = new LogicalEntityBuilder<TEntity>(QueryGenerator, Parameters, LogicalOperators.Or);
×
185

186
        builder(innerBuilder);
×
187

188
        var statement = innerBuilder.BuildStatement();
×
189

190
        if (statement != null && statement.Statement.HasValue())
×
191
            WhereExpressions.Add(new WhereExpression(statement.Statement, IsRaw: true));
×
192

193
        return this;
×
194
    }
195

196
    /// <summary>
197
    /// Adds a logical AND group to the WHERE clause using the specified builder action.
198
    /// </summary>
199
    /// <param name="builder">An action that configures the logical AND group using a <see cref="LogicalEntityBuilder{TEntity}"/>.</param>
200
    /// <returns>The builder instance for chaining further calls.</returns>
201
    public WhereEntityBuilder<TEntity> WhereAnd(Action<LogicalEntityBuilder<TEntity>> builder)
202
    {
203
        var innerBuilder = new LogicalEntityBuilder<TEntity>(QueryGenerator, Parameters, LogicalOperators.And);
×
204

205
        builder(innerBuilder);
×
206

207
        var statement = innerBuilder.BuildStatement();
×
208

209
        if (statement != null && statement.Statement.HasValue())
×
210
            WhereExpressions.Add(new WhereExpression(statement.Statement, IsRaw: true));
×
211

212
        return this;
×
213
    }
214

215
    /// <summary>
216
    /// Builds the SQL WHERE statement using the current expressions and parameters.
217
    /// </summary>
218
    /// <returns>
219
    /// A <see cref="QueryStatement"/> containing the SQL WHERE clause and its parameters,
220
    /// or <c>null</c> if no expressions are present.
221
    /// </returns>
222
    public override QueryStatement? BuildStatement()
223
    {
224
        if (WhereExpressions == null || WhereExpressions.Count == 0)
×
225
            return null;
×
226

227
        var statement = QueryGenerator.BuildWhere(WhereExpressions);
×
228

NEW
229
        if (statement.IsNullOrWhiteSpace())
×
NEW
230
            return null;
×
231

UNCOV
232
        return new QueryStatement(statement, Parameters);
×
233
    }
234

235
    private static IMemberAccessor GetPropertyAccessor<TValue>(Expression<Func<TEntity, TValue>> property)
236
    {
NEW
237
        var propertyAccessor = _typeAccessor.FindProperty(property);
×
NEW
238
        if (propertyAccessor is null)
×
NEW
239
            throw new ArgumentException("The specified property does not exist on the entity.", nameof(property));
×
240

NEW
241
        return propertyAccessor;
×
242
    }
243
}
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