Skip to content

Commit ccc984a

Browse files
committed
Makes possible to use Contains within Bulk operations
Performs rewrites like localCollection.Contains(value) -> value.In(localCollection)
1 parent 0f500e0 commit ccc984a

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

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

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Xtensive.Orm.BulkOperations
1414
internal abstract class QueryOperation<T> : Operation<T>
1515
where T : class, IEntity
1616
{
17-
private static MethodInfo inMethod = GetInMethod();
17+
private readonly static MethodInfo inMethod = GetInMethod();
1818
protected IQueryable<T> query;
1919

2020
protected QueryOperation(QueryProvider queryProvider)
@@ -24,8 +24,7 @@ protected QueryOperation(QueryProvider queryProvider)
2424

2525
private static MethodInfo GetInMethod()
2626
{
27-
foreach (var method in typeof (QueryableExtensions).GetMethods().Where(a=>a.Name=="In"))
28-
{
27+
foreach (var method in typeof (QueryableExtensions).GetMethods().Where(a=>a.Name == "In")) {
2928
var parameters = method.GetParameters();
3029
if (parameters.Length == 3 && parameters[2].ParameterType.Name == "IEnumerable`1")
3130
return method;
@@ -37,30 +36,38 @@ protected override int ExecuteInternal()
3736
{
3837
Expression e = query.Expression.Visit((MethodCallExpression ex) =>
3938
{
40-
if (ex.Method.DeclaringType == typeof (QueryableExtensions) && ex.Method.Name == "In" &&
41-
ex.Arguments.Count > 1)
42-
{
43-
if (ex.Arguments[1].Type == typeof (IncludeAlgorithm))
44-
{
45-
var v = (IncludeAlgorithm) ex.Arguments[1].Invoke();
46-
if (v == IncludeAlgorithm.TemporaryTable)
47-
{
39+
var methodInfo = ex.Method;
40+
//rewrite localCollection.Contains(entity.SomeField) -> entity.SomeField.In(localCollection)
41+
if (methodInfo.DeclaringType == typeof(Enumerable) &&
42+
methodInfo.Name == "Contains" &&
43+
ex.Arguments.Count == 2) {
44+
var localCollection = ex.Arguments[0];//IEnumerable<T>
45+
var valueToCheck = ex.Arguments[1];
46+
var genericInMethod = inMethod.MakeGenericMethod(new[] { valueToCheck.Type });
47+
ex = Expression.Call(genericInMethod, valueToCheck, Expression.Constant(IncludeAlgorithm.ComplexCondition), localCollection);
48+
methodInfo = ex.Method;
49+
}
50+
51+
if (methodInfo.DeclaringType == typeof(QueryableExtensions) &&
52+
methodInfo.Name == "In" &&
53+
ex.Arguments.Count > 1) {
54+
if (ex.Arguments[1].Type == typeof(IncludeAlgorithm)) {
55+
var algorithm = (IncludeAlgorithm) ex.Arguments[1].Invoke();
56+
if (algorithm == IncludeAlgorithm.TemporaryTable) {
4857
throw new NotSupportedException("IncludeAlgorithm.TemporaryTable is not supported");
4958
}
50-
if (v == IncludeAlgorithm.Auto)
51-
{
59+
if (algorithm == IncludeAlgorithm.Auto) {
5260
List<Expression> arguments = ex.Arguments.ToList();
5361
arguments[1] = Expression.Constant(IncludeAlgorithm.ComplexCondition);
54-
ex = Expression.Call(ex.Method, arguments);
62+
ex = Expression.Call(methodInfo, arguments);
5563
}
5664
}
57-
else
58-
{
65+
else {
5966
List<Expression> arguments = ex.Arguments.ToList();
6067
arguments.Insert(1, Expression.Constant(IncludeAlgorithm.ComplexCondition));
61-
List<Type> types = ex.Method.GetParameters().Select(a => a.ParameterType).ToList();
62-
types.Insert(1, typeof (IncludeAlgorithm));
63-
ex = Expression.Call(inMethod.MakeGenericMethod(ex.Method.GetGenericArguments()),
68+
List<Type> types = methodInfo.GetParameters().Select(a => a.ParameterType).ToList();
69+
types.Insert(1, typeof(IncludeAlgorithm));
70+
ex = Expression.Call(inMethod.MakeGenericMethod(methodInfo.GetGenericArguments()),
6471
arguments.ToArray());
6572
}
6673
}

0 commit comments

Comments
 (0)