• 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

73.17
/src/FluentCommand/Query/LogicalEntityBuilder.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 logical SQL query expressions (such as grouped AND/OR conditions) for a specific entity type with fluent, chainable methods.
11
/// </summary>
12
/// <typeparam name="TEntity">The type of the entity.</typeparam>
13
public class LogicalEntityBuilder<TEntity>
14
    : LogicalBuilder<LogicalEntityBuilder<TEntity>>, IWhereEntityBuilder<TEntity, LogicalEntityBuilder<TEntity>>
15
    where TEntity : class
16
{
17
    private static readonly TypeAccessor _typeAccessor = TypeAccessor.GetAccessor<TEntity>();
4✔
18

19
    /// <summary>
20
    /// Initializes a new instance of the <see cref="LogicalEntityBuilder{TEntity}"/> class.
21
    /// </summary>
22
    /// <param name="queryGenerator">The <see cref="IQueryGenerator"/> used to generate SQL expressions.</param>
23
    /// <param name="parameters">The list of <see cref="QueryParameter"/> objects for the query.</param>
24
    /// <param name="logicalOperator">The logical operator (<see cref="LogicalOperators"/>) to combine WHERE expressions. Defaults to <see cref="LogicalOperators.And"/>.</param>
25
    public LogicalEntityBuilder(
26
        IQueryGenerator queryGenerator,
27
        List<QueryParameter> parameters,
28
        LogicalOperators logicalOperator = LogicalOperators.And)
29
        : base(queryGenerator, parameters, logicalOperator)
7✔
30
    {
31
    }
7✔
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>
41
    /// The same builder instance for method chaining.
42
    /// </returns>
43
    public LogicalEntityBuilder<TEntity> Where<TValue>(
44
        Expression<Func<TEntity, TValue>> property,
45
        TValue? parameterValue,
46
        FilterOperators filterOperator = FilterOperators.Equal)
47
    {
48
        return Where(property, parameterValue, null, filterOperator);
10✔
49
    }
50

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

70
        return Where(propertyAccessor.Column, parameterValue, tableAlias, whereOperator);
10✔
71
    }
72

73
    /// <summary>
74
    /// Conditionally adds a WHERE clause for the specified property, value, and filter operator.
75
    /// </summary>
76
    /// <typeparam name="TValue">The type of the value to compare.</typeparam>
77
    /// <param name="property">An expression selecting the property to filter on.</param>
78
    /// <param name="parameterValue">The value to compare the property against.</param>
79
    /// <param name="filterOperator">The filter operator to use (default is <see cref="FilterOperators.Equal"/>).</param>
80
    /// <param name="condition">A function that determines whether to add the clause, based on the property name and value. If <c>null</c>, the clause is always added.</param>
81
    /// <returns>
82
    /// The same builder instance for method chaining.
83
    /// </returns>
84
    public LogicalEntityBuilder<TEntity> WhereIf<TValue>(
85
        Expression<Func<TEntity, TValue>> property,
86
        TValue? parameterValue,
87
        FilterOperators filterOperator = FilterOperators.Equal,
88
        Func<string, TValue?, bool>? condition = null)
89
    {
90
        return WhereIf(property, parameterValue, null, filterOperator, condition);
×
91
    }
92

93
    /// <summary>
94
    /// Conditionally adds a WHERE clause for the specified property, value, filter operator, and table alias.
95
    /// </summary>
96
    /// <typeparam name="TValue">The type of the value to compare.</typeparam>
97
    /// <param name="property">An expression selecting the property to filter on.</param>
98
    /// <param name="parameterValue">The value to compare the property against.</param>
99
    /// <param name="tableAlias">The table alias to use in the query.</param>
100
    /// <param name="filterOperator">The filter operator to use (default is <see cref="FilterOperators.Equal"/>).</param>
101
    /// <param name="condition">A function that determines whether to add the clause, based on the table alias and value. If <c>null</c>, the clause is always added.</param>
102
    /// <returns>
103
    /// The same builder instance for method chaining.
104
    /// </returns>
105
    public LogicalEntityBuilder<TEntity> WhereIf<TValue>(
106
        Expression<Func<TEntity, TValue>> property,
107
        TValue? parameterValue,
108
        string? tableAlias,
109
        FilterOperators filterOperator = FilterOperators.Equal,
110
        Func<string, TValue?, bool>? condition = null)
111
    {
NEW
112
        var propertyAccessor = GetPropertyAccessor(property);
×
113

114
        return WhereIf(propertyAccessor.Column, parameterValue, tableAlias, filterOperator, condition);
×
115
    }
116

117
    /// <summary>
118
    /// Adds a WHERE IN clause for the specified property and collection of values, with an optional table alias.
119
    /// </summary>
120
    /// <typeparam name="TValue">The type of the values to compare.</typeparam>
121
    /// <param name="property">An expression selecting the property to filter on.</param>
122
    /// <param name="parameterValues">The collection of values for the IN clause.</param>
123
    /// <param name="tableAlias">The table alias to use in the query (optional).</param>
124
    /// <returns>
125
    /// The same builder instance for method chaining.
126
    /// </returns>
127
    public LogicalEntityBuilder<TEntity> WhereIn<TValue>(
128
        Expression<Func<TEntity, TValue>> property,
129
        IEnumerable<TValue> parameterValues,
130
        string? tableAlias = null)
131
    {
NEW
132
        var propertyAccessor = GetPropertyAccessor(property);
×
133

NEW
134
        return WhereIn(propertyAccessor.Column, parameterValues, tableAlias);
×
135
    }
136

137
    /// <summary>
138
    /// Conditionally adds a WHERE IN clause for the specified property and collection of values.
139
    /// </summary>
140
    /// <typeparam name="TValue">The type of the values to compare.</typeparam>
141
    /// <param name="property">An expression selecting the property to filter on.</param>
142
    /// <param name="parameterValues">The collection of values for the IN clause.</param>
143
    /// <param name="condition">A function that determines whether to add the clause, based on the property name and values. If <c>null</c>, the clause is always added.</param>
144
    /// <returns>
145
    /// The same builder instance for method chaining.
146
    /// </returns>
147
    public LogicalEntityBuilder<TEntity> WhereInIf<TValue>(
148
        Expression<Func<TEntity, TValue>> property,
149
        IEnumerable<TValue> parameterValues,
150
        Func<string, IEnumerable<TValue>, bool>? condition = null)
151
    {
NEW
152
        var propertyAccessor = GetPropertyAccessor(property);
×
153

NEW
154
        return WhereInIf(propertyAccessor.Column, parameterValues, condition);
×
155
    }
156

157
    /// <summary>
158
    /// Conditionally adds a WHERE IN clause for the specified property, collection of values, and table alias.
159
    /// </summary>
160
    /// <typeparam name="TValue">The type of the values to compare.</typeparam>
161
    /// <param name="property">An expression selecting the property to filter on.</param>
162
    /// <param name="parameterValues">The collection of values for the IN clause.</param>
163
    /// <param name="tableAlias">The table alias to use in the query.</param>
164
    /// <param name="condition">A function that determines whether to add the clause, based on the table alias and values. If <c>null</c>, the clause is always added.</param>
165
    /// <returns>
166
    /// The same builder instance for method chaining.
167
    /// </returns>
168
    public LogicalEntityBuilder<TEntity> WhereInIf<TValue>(
169
        Expression<Func<TEntity, TValue>> property,
170
        IEnumerable<TValue> parameterValues,
171
        string? tableAlias,
172
        Func<string, IEnumerable<TValue>, bool>? condition = null)
173
    {
NEW
174
        var propertyAccessor = GetPropertyAccessor(property);
×
175

NEW
176
        return WhereInIf(propertyAccessor.Column, parameterValues, tableAlias, condition);
×
177
    }
178

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

190
        builder(innerBuilder);
1✔
191

192
        var statement = innerBuilder.BuildStatement();
1✔
193

194
        if (statement?.Statement.HasValue() == true)
1✔
195
            WhereExpressions.Add(new WhereExpression(statement.Statement, IsRaw: true));
1✔
196

197
        return this;
1✔
198
    }
199

200
    /// <summary>
201
    /// Adds a logical AND group to the WHERE clause using the specified builder action.
202
    /// </summary>
203
    /// <param name="builder">An action that configures the logical AND group using a <see cref="LogicalEntityBuilder{TEntity}"/>.</param>
204
    /// <returns>
205
    /// The same builder instance for method chaining.
206
    /// </returns>
207
    public LogicalEntityBuilder<TEntity> WhereAnd(Action<LogicalEntityBuilder<TEntity>> builder)
208
    {
209
        var innerBuilder = new LogicalEntityBuilder<TEntity>(QueryGenerator, Parameters, LogicalOperators.And);
1✔
210

211
        builder(innerBuilder);
1✔
212

213
        var statement = innerBuilder.BuildStatement();
1✔
214

215
        if (statement?.Statement.HasValue() == true)
1✔
216
            WhereExpressions.Add(new WhereExpression(statement.Statement, IsRaw: true));
1✔
217

218
        return this;
1✔
219
    }
220

221
    private static IMemberAccessor GetPropertyAccessor<TValue>(Expression<Func<TEntity, TValue>> property)
222
    {
223
        var propertyAccessor = _typeAccessor.FindProperty(property);
10✔
224
        if (propertyAccessor is null)
10!
NEW
225
            throw new ArgumentException("The specified property does not exist on the entity.", nameof(property));
×
226

227
        return propertyAccessor;
10✔
228
    }
229
}
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