• 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

75.93
/src/FluentCommand/Query/InsertEntityBuilder.cs
1
using System.Linq.Expressions;
2

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

6
namespace FluentCommand.Query;
7

8
/// <summary>
9
/// Provides a builder for constructing SQL INSERT statements for a specific entity type with fluent, chainable methods.
10
/// </summary>
11
/// <typeparam name="TEntity">The type of the entity.</typeparam>
12
public class InsertEntityBuilder<TEntity> : InsertBuilder<InsertEntityBuilder<TEntity>>
13
    where TEntity : class
14
{
15
    private static readonly TypeAccessor _typeAccessor = TypeAccessor.GetAccessor<TEntity>();
5✔
16

17
    /// <summary>
18
    /// Initializes a new instance of the <see cref="InsertEntityBuilder{TEntity}"/> class.
19
    /// </summary>
20
    /// <param name="queryGenerator">The <see cref="IQueryGenerator"/> used to generate SQL expressions.</param>
21
    /// <param name="parameters">The list of <see cref="QueryParameter"/> objects for the query.</param>
22
    public InsertEntityBuilder(
23
        IQueryGenerator queryGenerator,
24
        List<QueryParameter> parameters)
25
        : base(queryGenerator, parameters)
12✔
26
    {
27
    }
12✔
28

29
    /// <summary>
30
    /// Adds a value for the specified entity property and value.
31
    /// </summary>
32
    /// <typeparam name="TValue">The type of the value.</typeparam>
33
    /// <param name="property">An expression selecting the property to insert.</param>
34
    /// <param name="parameterValue">The value to insert for the property.</param>
35
    /// <returns>
36
    /// The same builder instance for method chaining.
37
    /// </returns>
38
    public InsertEntityBuilder<TEntity> Value<TValue>(
39
        Expression<Func<TEntity, TValue>> property,
40
        TValue? parameterValue)
41
    {
42
        var propertyAccessor = GetPropertyAccessor(property);
20✔
43
        return Value(propertyAccessor.Column, parameterValue);
20✔
44
    }
45

46
    /// <summary>
47
    /// Conditionally adds a value for the specified entity property and value if the condition is met.
48
    /// </summary>
49
    /// <typeparam name="TValue">The type of the value.</typeparam>
50
    /// <param name="property">An expression selecting the property to insert.</param>
51
    /// <param name="parameterValue">The value to insert for the property.</param>
52
    /// <param name="condition">A function that determines whether to add the value, based on the property name and value. If <c>null</c>, the value is always added.</param>
53
    /// <returns>
54
    /// The same builder instance for method chaining.
55
    /// </returns>
56
    public InsertEntityBuilder<TEntity> ValueIf<TValue>(
57
        Expression<Func<TEntity, TValue>> property,
58
        TValue? parameterValue,
59
        Func<string, TValue?, bool> condition)
60
    {
NEW
61
        var propertyAccessor = GetPropertyAccessor(property);
×
62
        return ValueIf(propertyAccessor.Column, parameterValue, condition);
×
63
    }
64

65
    /// <summary>
66
    /// Adds values from the specified entity. If column names are provided,
67
    /// only those that match an entity property name will be included.
68
    /// </summary>
69
    /// <param name="entity">The entity to insert.</param>
70
    /// <param name="columnNames">The column names to include (optional).</param>
71
    /// <returns>
72
    /// The same builder instance for method chaining.
73
    /// </returns>
74
    /// <exception cref="ArgumentNullException">Thrown if <paramref name="entity"/> is <c>null</c>.</exception>
75
    public InsertEntityBuilder<TEntity> Values(
76
        TEntity entity,
77
        IEnumerable<string>? columnNames = null)
78
    {
79
        if (entity is null)
8!
80
            throw new ArgumentNullException(nameof(entity));
×
81

82
        var properties = _typeAccessor.GetProperties();
8✔
83
        if (properties == null)
8!
NEW
84
            return this;
×
85

86
        var columnSet = new HashSet<string>(columnNames ?? []);
8✔
87

88
        foreach (var property in properties)
390✔
89
        {
90

91
            if (columnSet.Count > 0 && !columnSet.Contains(property.Column))
187!
92
                continue;
93

94
            if (property.IsNotMapped || property.IsDatabaseGenerated)
187✔
95
                continue;
96

97
            // include the type to prevent issues with null
98
            Value(property.Column, property.GetValue(entity), property.MemberType);
152✔
99
        }
100

101
        return this;
8✔
102
    }
103

104
    /// <summary>
105
    /// Adds an OUTPUT clause for the specified entity property.
106
    /// </summary>
107
    /// <typeparam name="TValue">The type of the property value.</typeparam>
108
    /// <param name="property">An expression selecting the property to output.</param>
109
    /// <param name="tableAlias">The alias for the table (optional).</param>
110
    /// <param name="columnAlias">The alias for the output column (optional).</param>
111
    /// <returns>
112
    /// The same builder instance for method chaining.
113
    /// </returns>
114
    public InsertEntityBuilder<TEntity> Output<TValue>(
115
        Expression<Func<TEntity, TValue>> property,
116
        string? tableAlias = null,
117
        string? columnAlias = null)
118
    {
119
        var propertyAccessor = GetPropertyAccessor(property);
11✔
120
        return Output(propertyAccessor.Column, tableAlias, columnAlias);
11✔
121
    }
122

123
    /// <summary>
124
    /// Conditionally adds an OUTPUT clause for the specified entity property if the condition is met.
125
    /// </summary>
126
    /// <typeparam name="TValue">The type of the property value.</typeparam>
127
    /// <param name="property">An expression selecting the property to output.</param>
128
    /// <param name="tableAlias">The alias for the table (optional).</param>
129
    /// <param name="columnAlias">The alias for the output column (optional).</param>
130
    /// <param name="condition">A function that determines whether to add the OUTPUT clause. If <c>null</c>, the clause is always added.</param>
131
    /// <returns>
132
    /// The same builder instance for method chaining.
133
    /// </returns>
134
    public InsertEntityBuilder<TEntity> OutputIf<TValue>(
135
        Expression<Func<TEntity, TValue>> property,
136
        string? tableAlias = null,
137
        string? columnAlias = null,
138
        Func<string, bool>? condition = null)
139
    {
NEW
140
        var propertyAccessor = GetPropertyAccessor(property);
×
141
        return OutputIf(propertyAccessor.Column, tableAlias, columnAlias, condition);
×
142
    }
143

144
    /// <summary>
145
    /// Builds the SQL INSERT statement using the current configuration.
146
    /// </summary>
147
    /// <returns>
148
    /// A <see cref="QueryStatement"/> containing the SQL INSERT statement and its parameters.
149
    /// </returns>
150
    public override QueryStatement? BuildStatement()
151
    {
152
        // add table and schema from attribute if not set
153
        if (TableExpression == null)
12✔
154
            Into(_typeAccessor.TableName, _typeAccessor.TableSchema);
12✔
155

156
        return base.BuildStatement();
12✔
157
    }
158

159
    private static IMemberAccessor GetPropertyAccessor<TModel, TValue>(
160
        TypeAccessor typeAccessor,
161
        Expression<Func<TModel, TValue>> property)
162
    {
163
        if (property is null)
31!
NEW
164
            throw new ArgumentNullException(nameof(property));
×
165

166
        var propertyAccessor = typeAccessor.FindProperty(property);
31✔
167
        if (propertyAccessor is null)
31!
NEW
168
            throw new ArgumentException("The specified property does not exist on the entity.", nameof(property));
×
169

170
        return propertyAccessor;
31✔
171
    }
172

173
    private static IMemberAccessor GetPropertyAccessor<TValue>(Expression<Func<TEntity, TValue>> property)
174
        => GetPropertyAccessor(_typeAccessor, property);
31✔
175

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