protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var functions = Sql.ExtensionAttribute.GetExtensionAttributes(methodCall, builder.MappingSchema); var root = methodCall.SkipMethodChain(builder.MappingSchema); // evaluating IQueryableContainer while (root.NodeType == ExpressionType.Constant && typeof(Sql.IQueryableContainer).IsSameOrParentOf(root.Type)) { root = ((Sql.IQueryableContainer)root.EvaluateExpression() !).Query.Expression; root = root.SkipMethodChain(builder.MappingSchema); } root = builder.ConvertExpressionTree(root); var sequence = builder.BuildSequence(new BuildInfo(buildInfo, root) { CreateSubQuery = true }); var finalFunction = functions.First(); var sqlExpression = finalFunction.GetExpression(builder.DataContext, buildInfo.SelectQuery, methodCall, (e, descriptor) => builder.ConvertToExtensionSql(sequence, e, descriptor)); var context = new ChainContext(buildInfo.Parent, sequence, methodCall); context.Sql = context.SelectQuery; context.FieldIndex = context.SelectQuery.Select.Add(sqlExpression, methodCall.Method.Name); return(context); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var functions = Sql.ExtensionAttribute.GetExtensionAttributes(methodCall, builder.MappingSchema); var chain = Sql.ExtensionAttribute.BuildFunctionsChain(builder.MappingSchema, methodCall); IBuildContext sequence = null; foreach (var expression in chain) { if (expression is MethodCallExpression mc) { if (mc.Arguments.Count > 0) { if (typeof(IEnumerable <>).IsSameOrParentOf(mc.Arguments[0].Type)) { sequence = builder.BuildSequence(new BuildInfo(buildInfo, mc.Arguments[0]) { IsChain = true }); } else if (typeof(Sql.IQueryableContainer).IsSameOrParentOf(mc.Arguments[0].Type)) { sequence = builder.BuildSequence(new BuildInfo(buildInfo, ((Sql.IQueryableContainer)mc.Arguments[0].EvaluateExpression()).Query.Expression) { IsChain = true }); } } } } if (sequence == null) { throw new LinqToDBException($"{methodCall} can not be converted to SQL."); } if (buildInfo.IsChain) { // it means that function is just sequence provider return(sequence); } var finalFunction = functions.First(); var sqlExpression = finalFunction.GetExpression(builder.DataContext, buildInfo.SelectQuery, methodCall, e => builder.ConvertToExtensionSql(sequence, e)); var context = new ChainContext(buildInfo.Parent, sequence, methodCall); context.Sql = context.SelectQuery; context.FieldIndex = context.SelectQuery.Select.Add(sqlExpression, methodCall.Method.Name); return(context); }