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

loresoft / FluentCommand / 26594173245

28 May 2026 06:28PM UTC coverage: 55.553% (+0.7%) from 54.902%
26594173245

push

github

pwelter34
Move JSON support, add docs and examples

1358 of 3215 branches covered (42.24%)

Branch coverage included in aggregate %.

103 of 234 new or added lines in 9 files covered. (44.02%)

371 existing lines in 26 files now uncovered.

4389 of 7130 relevant lines covered (61.56%)

312.89 hits per line

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

77.08
/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
    {
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
        ArgumentNullException.ThrowIfNull(entity);
8✔
80

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

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

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

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

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

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

100
        return this;
8✔
101
    }
102

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

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

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

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

158
    private static IMemberAccessor GetPropertyAccessor<TModel, TValue>(
159
        TypeAccessor typeAccessor,
160
        Expression<Func<TModel, TValue>> property)
161
    {
162
        ArgumentNullException.ThrowIfNull(property);
31✔
163

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

168
        return propertyAccessor;
31✔
169
    }
170

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

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