Skip to content

Commit ccf7830

Browse files
authored
Merge pull request #236 from servicetitan/upstream/optimize_bulk
Optimization: avoid Lambda JITing for typical case of invoking Bulk Set() with value
2 parents ac24399 + 9b75b4b commit ccf7830

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

Extensions/Xtensive.Orm.BulkOperations/BulkExtensions.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,14 @@ public static IUpdatable<T> Set<T, TResult>(this IUpdatable<T> query, Expression
7878
/// <returns>Instance of <see cref=" IUpdatable&lt;T&gt;"/>.</returns>
7979
[Pure]
8080
public static IUpdatable<T> Set<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> field,
81-
TResult value) where T: IEntity =>
82-
Set(query, field, a => value);
81+
TResult value) where T: IEntity
82+
{
83+
// Manually constructed expression is simpler than `a => value`
84+
var valueFunc = Expression.Lambda<Func<T, TResult>>(Expression.Constant(value, typeof(TResult)),
85+
Expression.Parameter(typeof(T), "a"));
86+
87+
return Set(query, field, valueFunc);
88+
}
8389

8490
/// <summary>
8591
/// Executes bulk update of entities specified by the query.

Extensions/Xtensive.Orm.BulkOperations/Internals/AddValueContext.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq.Expressions;
1+
using System.Linq.Expressions;
2+
using Xtensive.Linq;
23
using Xtensive.Orm.Model;
34
using Xtensive.Sql.Dml;
45

@@ -16,5 +17,10 @@ internal class AddValueContext
1617
public FieldInfo Field { get; set; }
1718

1819
public bool SubqueryExists { get; set; }
20+
21+
public object EvalLambdaBody() =>
22+
Lambda.Body is ConstantExpression ce
23+
? ce.Value
24+
: FastExpression.Lambda(Lambda.Body).Compile().DynamicInvoke();
1925
}
20-
}
26+
}

Extensions/Xtensive.Orm.BulkOperations/Internals/SetOperation.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private void AddComputedExpression(AddValueContext addContext)
136136
var sqlSelect = request.Query;
137137
SqlExpression ex = sqlSelect.OrderBy[0].Expression;
138138
parent.Bindings.AddRange(request.ParameterBindings);
139-
139+
140140
if(parent.JoinedTableRef!=null)
141141
ex.AcceptVisitor(new ComputedExpressionSqlVisitor(sqlSelect.From, parent.JoinedTableRef));
142142

@@ -146,10 +146,11 @@ private void AddComputedExpression(AddValueContext addContext)
146146
private void AddConstantValue(AddValueContext addContext)
147147
{
148148
SqlTableColumn column = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Column.Name);
149+
var constant = addContext.EvalLambdaBody();
149150
SqlExpression value;
150-
object constant = FastExpression.Lambda(addContext.Lambda.Body).Compile().DynamicInvoke();
151-
if (constant==null)
151+
if (constant == null) {
152152
value = SqlDml.Null;
153+
}
153154
else {
154155
QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(constant.GetType(), context => constant);
155156
parent.Bindings.Add(binding);
@@ -223,7 +224,8 @@ private void AddEntityValue(AddValueContext addContext)
223224
}
224225
}
225226
i = -1;
226-
var entity = (IEntity) FastExpression.Lambda(addContext.Lambda.Body).Compile().DynamicInvoke();
227+
var entity = (IEntity)addContext.EvalLambdaBody();
228+
227229
foreach (ColumnInfo column in addContext.Field.Columns) {
228230
i++;
229231
SqlExpression value;

0 commit comments

Comments
 (0)