bool PreferServerSide(Expression expr) { switch (expr.NodeType) { case ExpressionType.MemberAccess: { var pi = (MemberExpression)expr; var l = SqlProvider.ConvertMember(pi.Member); if (l != null) { var info = l.Body.Unwrap(); if (l.Parameters.Count == 1 && pi.Expression != null) { info = info.Convert(wpi => wpi == l.Parameters[0] ? pi.Expression : wpi); } return(info.Find(PreferServerSide) != null); } var attr = GetFunctionAttribute(pi.Member); return(attr != null && attr.PreferServerSide && !CanBeCompiled(expr)); } case ExpressionType.Call: { var pi = (MethodCallExpression)expr; var e = pi; var l = SqlProvider.ConvertMember(e.Method); if (l != null) { return(l.Body.Unwrap().Find(PreferServerSide) != null); } var attr = GetFunctionAttribute(e.Method); return(attr != null && attr.PreferServerSide && !CanBeCompiled(expr)); } } return(false); }
public Expression BuildExpression(IBuildContext context, Expression expression) { var newExpr = expression.Convert2(pi => { if (_skippedExpressions.Contains(pi)) { return(new ExpressionHelper.ConvertInfo(pi, true)); } switch (pi.NodeType) { case ExpressionType.MemberAccess: { if (IsServerSideOnly(pi) || PreferServerSide(pi)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, pi))); } var ma = (MemberExpression)pi; if (SqlProvider.ConvertMember(ma.Member) != null) { break; } /* * var res = context.IsExpression(pi, 0, RequestFor.Association); * * if (res.Result) * { * var table = (TableBuilder.AssociatedTableContext)res.Context; * * if (table.IsList) * return new ExpressionHelper.ConvertInfo(BuildMultipleQuery(context, pi)); * } */ var ctx = GetContext(context, pi); if (ctx != null) { return(new ExpressionHelper.ConvertInfo(ctx.BuildExpression(pi, 0))); } var ex = ma.Expression; if (ex != null && ex.NodeType == ExpressionType.Constant) { // field = localVariable // var c = _expressionAccessors[ex]; return(new ExpressionHelper.ConvertInfo( Expression.MakeMemberAccess(Expression.Convert(c, ex.Type), ma.Member))); } break; } case ExpressionType.Parameter: { if (pi == ParametersParam) { break; } var ctx = GetContext(context, pi); if (ctx != null) { return(new ExpressionHelper.ConvertInfo(ctx.BuildExpression(pi, 0))); } break; } case ExpressionType.Constant: { if (ExpressionHelper.IsConstant(pi.Type)) { break; } if (_expressionAccessors.ContainsKey(pi)) { return(new ExpressionHelper.ConvertInfo(Expression.Convert(_expressionAccessors[pi], pi.Type))); } break; } case ExpressionType.Coalesce: if (pi.Type == typeof(string) && MappingSchema.GetDefaultNullValue <string>() != null) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, pi))); } if (CanBeTranslatedToSql(context, ConvertExpression(pi), true)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, pi))); } break; case ExpressionType.Conditional: if (CanBeTranslatedToSql(context, ConvertExpression(pi), true)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, pi))); } break; case ExpressionType.Call: { var ce = (MethodCallExpression)pi; if (IsGroupJoinSource(context, ce)) { foreach (var arg in ce.Arguments.Skip(1)) { if (!_skippedExpressions.Contains(arg)) { _skippedExpressions.Add(arg); } } break; } if (IsSubQuery(context, ce)) { if (TypeHelper.IsSameOrParent(typeof(IEnumerable), pi.Type)) { return(new ExpressionHelper.ConvertInfo(BuildMultipleQuery(context, pi))); } return(new ExpressionHelper.ConvertInfo(GetSubQuery(context, ce).BuildExpression(null, 0))); } if (IsServerSideOnly(pi) || PreferServerSide(pi)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, pi))); } } break; } if (EnforceServerSide(context)) { switch (pi.NodeType) { case ExpressionType.MemberInit: case ExpressionType.New: case ExpressionType.Convert: break; default: if (CanBeCompiled(pi)) { break; } return(new ExpressionHelper.ConvertInfo(BuildSql(context, pi))); } } return(new ExpressionHelper.ConvertInfo(pi)); }); return(newExpr); }
public Expression BuildExpression(IBuildContext context, Expression expression) { var newExpr = expression.Convert2(expr => { if (_skippedExpressions.Contains(expr)) { return(new ExpressionHelper.ConvertInfo(expr, true)); } if (expr.Find(IsNoneSqlMember) != null) { return(new ExpressionHelper.ConvertInfo(expr)); } switch (expr.NodeType) { case ExpressionType.MemberAccess: { if (IsServerSideOnly(expr) || PreferServerSide(expr)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, expr))); } var ma = (MemberExpression)expr; if (SqlProvider.ConvertMember(ma.Member) != null) { break; } var ctx = GetContext(context, expr); if (ctx != null) { return(new ExpressionHelper.ConvertInfo(ctx.BuildExpression(expr, 0))); } var ex = ma.Expression; if (ex != null && ex.NodeType == ExpressionType.Constant) { // field = localVariable // var c = _expressionAccessors[ex]; return(new ExpressionHelper.ConvertInfo( Expression.MakeMemberAccess(Expression.Convert(c, ex.Type), ma.Member))); } break; } case ExpressionType.Parameter: { if (expr == ParametersParam) { break; } var ctx = GetContext(context, expr); if (ctx != null) { return(new ExpressionHelper.ConvertInfo(ctx.BuildExpression(expr, 0))); } break; } case ExpressionType.Constant: { if (ExpressionHelper.IsConstant(expr.Type)) { break; } if (_expressionAccessors.ContainsKey(expr)) { return(new ExpressionHelper.ConvertInfo(Expression.Convert(_expressionAccessors[expr], expr.Type))); } break; } case ExpressionType.Coalesce: if (expr.Type == typeof(string) && MappingSchema.GetDefaultNullValue <string>() != null) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, expr))); } if (CanBeTranslatedToSql(context, ConvertExpression(expr), true)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, expr))); } break; case ExpressionType.Conditional: if (CanBeTranslatedToSql(context, ConvertExpression(expr), true)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, expr))); } break; case ExpressionType.Call: { var ce = (MethodCallExpression)expr; if (IsGroupJoinSource(context, ce)) { foreach (var arg in ce.Arguments.Skip(1)) { if (!_skippedExpressions.Contains(arg)) { _skippedExpressions.Add(arg); } } break; } if (IsSubQuery(context, ce)) { if (TypeHelper.IsSameOrParent(typeof(IEnumerable), expr.Type) && expr.Type != typeof(string) && !expr.Type.IsArray) { return(new ExpressionHelper.ConvertInfo(BuildMultipleQuery(context, expr))); } return(new ExpressionHelper.ConvertInfo(GetSubQuery(context, ce).BuildExpression(null, 0))); } if (IsServerSideOnly(expr) || PreferServerSide(expr)) { return(new ExpressionHelper.ConvertInfo(BuildSql(context, expr))); } } break; } if (EnforceServerSide(context)) { switch (expr.NodeType) { case ExpressionType.MemberInit: case ExpressionType.New: case ExpressionType.Convert: break; default: if (CanBeCompiled(expr)) { break; } return(new ExpressionHelper.ConvertInfo(BuildSql(context, expr))); } } return(new ExpressionHelper.ConvertInfo(expr)); }); return(newExpr); }