protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var query = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var except = query.SqlQuery; sequence = new SubQueryContext(sequence); var sql = sequence.SqlQuery; except.ParentSql = sql; if (methodCall.Method.Name == "Except") sql.Where.Not.Exists(except); else sql.Where.Exists(except); var keys1 = sequence.ConvertToSql(null, 0, ConvertFlags.Key); var keys2 = query. ConvertToSql(null, 0, ConvertFlags.Key); if (keys1.Length != keys2.Length) throw new InvalidOperationException(); for (var i = 0; i < keys1.Length; i++) { except.Where .Expr(keys1[i].Sql) .Equal .Expr(keys2[i].Sql); } return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SqlQuery.Select.TakeValue != null || sequence.SqlQuery.Select.SkipValue != null) sequence = new SubQueryContext(sequence); var lambda = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var sparent = sequence.Parent; var order = new ExpressionContext(buildInfo.Parent, sequence, lambda); var body = lambda.Body.Unwrap(); var sql = builder.ConvertExpressions(order, body, ConvertFlags.Key); builder.ReplaceParent(order, sparent); //if (!methodCall.Method.Name.StartsWith("Then")) // sequence.SqlQuery.OrderBy.Items.Clear(); foreach (var expr in sql) { var e = builder.ConvertSearchCondition(sequence, expr.Sql); sequence.SqlQuery.OrderBy.Expr(e, methodCall.Method.Name.EndsWith("Descending")); } return sequence; }
protected override SequenceConvertInfo Convert( ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) { var predicate = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), predicate.Parameters[0]); if (info != null) { info.Expression = methodCall.Convert(ex => ConvertMethod(methodCall, 0, info, predicate.Parameters[0], ex)); if (param != null) { if (param.Type != info.Parameter.Type) param = Expression.Parameter(info.Parameter.Type, param.Name); if (info.ExpressionsToReplace != null) foreach (var path in info.ExpressionsToReplace) { path.Path = path.Path.Convert(e => e == info.Parameter ? param : e); path.Expr = path.Expr.Convert(e => e == info.Parameter ? param : e); } } info.Parameter = param; return info; } return null; }
static void BuildSkip(ExpressionBuilder builder, IBuildContext sequence, ISqlExpression prevSkipValue, ISqlExpression expr) { var sql = sequence.SqlQuery; builder.SqlProvider.SqlQuery = sql; sql.Select.Skip(expr); builder.SqlProvider.SqlQuery = sql; if (sql.Select.TakeValue != null) { if (builder.SqlProvider.IsSkipSupported || !builder.SqlProvider.IsTakeSupported) sql.Select.Take(builder.Convert( sequence, new SqlBinaryExpression(typeof(int), sql.Select.TakeValue, "-", sql.Select.SkipValue, Precedence.Additive))); if (prevSkipValue != null) sql.Select.Skip(builder.Convert( sequence, new SqlBinaryExpression(typeof(int), prevSkipValue, "+", sql.Select.SkipValue, Precedence.Additive))); } if (!builder.SqlProvider.TakeAcceptsParameter) { var p = sql.Select.SkipValue as SqlParameter; if (p != null) p.IsQueryParameter = false; } }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var condition = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var result = builder.BuildWhere(buildInfo.Parent, sequence, condition, true); result.SetAlias(condition.Parameters[0].Name); return result; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sql = sequence.SqlQuery; if (sql.Select.TakeValue != null || sql.Select.SkipValue != null) sequence = new SubQueryContext(sequence); sequence.SqlQuery.Select.IsDistinct = true; return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence1 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var sequence2 = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var union = new SqlQuery.Union(sequence2.SqlQuery, methodCall.Method.Name == "Concat"); var sq = sequence1 as SubQueryContext; if (sq == null || sq.Union != null || !sq.SqlQuery.IsSimple) sq = new SubQueryContext(sequence1); sq.SubQuery.SqlQuery.Unions.Add(union); sq.Union = sequence2; return sq; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var table = (TableBuilder.TableContext)sequence; var value = (string)((ConstantExpression)methodCall.Arguments[1]).Value; switch (methodCall.Method.Name) { case "TableName" : table.SqlTable.PhysicalName = value; break; case "DatabaseName" : table.SqlTable.Database = value; break; case "OwnerName" : table.SqlTable.Owner = value; break; } return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var defaultValue = methodCall.Arguments.Count == 1 ? null : methodCall.Arguments[1].Unwrap(); if (buildInfo.Parent is SelectManyBuilder.SelectManyContext) { var groupJoin = ((SelectManyBuilder.SelectManyContext)buildInfo.Parent).Sequence[0] as JoinBuilder.GroupJoinContext; if (groupJoin != null) { groupJoin.SqlQuery.From.Tables[0].Joins[0].JoinType = SqlQuery.JoinType.Left; groupJoin.SqlQuery.From.Tables[0].Joins[0].IsWeak = false; } } return new DefaultIfEmptyContext(buildInfo.Parent, sequence, defaultValue); }
static void BuildTake(ExpressionBuilder builder, IBuildContext sequence, ISqlExpression expr) { var sql = sequence.SqlQuery; builder.SqlProvider.SqlQuery = sql; sql.Select.Take(expr); if (sql.Select.SkipValue != null && builder.SqlProvider.IsTakeSupported && !builder.SqlProvider.IsSkipSupported) { if (sql.Select.SkipValue is SqlParameter && sql.Select.TakeValue is SqlValue) { var skip = (SqlParameter)sql.Select.SkipValue; var parm = (SqlParameter)sql.Select.SkipValue.Clone(new Dictionary<ICloneableElement,ICloneableElement>(), _ => true); parm.SetTakeConverter((int)((SqlValue)sql.Select.TakeValue).Value); sql.Select.Take(parm); var ep = (from pm in builder.CurrentSqlParameters where pm.SqlParameter == skip select pm).First(); ep = new ParameterAccessor { Expression = ep.Expression, Accessor = ep.Accessor, SqlParameter = parm }; builder.CurrentSqlParameters.Add(ep); } else sql.Select.Take(builder.Convert( sequence, new SqlBinaryExpression(typeof(int), sql.Select.SkipValue, "+", sql.Select.TakeValue, Precedence.Additive))); } if (!builder.SqlProvider.TakeAcceptsParameter) { var p = sql.Select.TakeValue as SqlParameter; if (p != null) p.IsQueryParameter = false; } }
protected override SequenceConvertInfo Convert( ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) { var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), null); if (info != null) { info.Expression = Expression.Call( methodCall.Method.DeclaringType, methodCall.Method.Name, new[] { info.Expression.Type.GetGenericArguments()[0] }, info.Expression, methodCall.Arguments[1]); info.Parameter = param; return info; } return null; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var table = sequence as TableBuilder.TableContext; if (table != null && table.InheritanceMapping.Count > 0) { var objectType = methodCall.Type.GetGenericArguments()[0]; if (TypeHelper.IsSameOrParent(table.ObjectType, objectType)) { var predicate = builder.MakeIsPredicate(table, objectType); if (predicate.GetType() != typeof(SqlQuery.Predicate.Expr)) sequence.SqlQuery.Where.SearchCondition.Conditions.Add(new SqlQuery.Condition(false, predicate)); } } return sequence; }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var arg = methodCall.Arguments[1].Unwrap(); if (arg.NodeType == ExpressionType.Lambda) arg = ((LambdaExpression)arg).Body.Unwrap(); var expr = builder.ConvertToSql(sequence, arg, false); if (methodCall.Method.Name == "Take") { BuildTake(builder, sequence, expr); } else { BuildSkip(builder, sequence, sequence.SqlQuery.Select.SkipValue, expr); } return sequence; }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { if (!methodCall.IsQueryable("OrderBy", "OrderByDescending", "ThenBy", "ThenByDescending")) return false; var body = ((LambdaExpression)methodCall.Arguments[1].Unwrap()).Body.Unwrap(); if (body.NodeType == ExpressionType.MemberInit) { var mi = (MemberInitExpression)body; bool throwExpr; if (mi.NewExpression.Arguments.Count > 0 || mi.Bindings.Count == 0) throwExpr = true; else throwExpr = mi.Bindings.Any(b => b.BindingType != MemberBindingType.Assignment); if (throwExpr) throw new NotSupportedException(string.Format("Explicit construction of entity type '{0}' in order by is not allowed.", body.Type)); } return true; }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return methodCall.IsQueryable("Skip", "Take"); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.Arguments.Count == 2 && methodCall.IsQueryable("Concat", "Union")); }
public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo) { if (buildInfo.Expression.NodeType == ExpressionType.Call) return CanBuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo); return false; }
protected abstract bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo);
protected abstract SequenceConvertInfo Convert (ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param);
public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param) { return Convert(builder, (MethodCallExpression)buildInfo.Expression, buildInfo, param); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsQueryable("DefaultIfEmpty")); }
protected abstract IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo);
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SqlQuery.Select.IsDistinct; if (isSubQuery) { sequence = new SubQueryContext(sequence); } switch (methodCall.Arguments.Count) { case 1: // static int Insert<T> (this IValueInsertable<T> source) // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source) { foreach (var item in sequence.SqlQuery.Insert.Items) { sequence.SqlQuery.Select.Expr(item.Expression); } break; } case 2: // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter) { UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[1].Unwrap(), sequence, sequence.SqlQuery.Insert.Items, sequence); sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.From.Tables.Clear(); break; } case 3: // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter) { var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence.SqlQuery.Insert.Items, sequence); sequence.SqlQuery.Select.Columns.Clear(); foreach (var item in sequence.SqlQuery.Insert.Items) { sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression)); } sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)into).SqlTable; break; } } var insert = sequence.SqlQuery.Insert; var q = insert.Into.Fields.Values.Cast <ISqlExpression>().Except(insert.Items.Select(e => e.Column)) .OfType <SqlField>() .Where(f => f.IsIdentity); foreach (var field in q) { var expr = builder.SqlProvider.GetIdentityExpression(insert.Into, field, false); if (expr != null) { insert.Items.Insert(0, new SqlQuery.SetExpression(field, expr)); if (methodCall.Arguments.Count == 3) { sequence.SqlQuery.Select.Columns.Insert(0, new SqlQuery.Column(sequence.SqlQuery, insert.Items[0].Expression)); } } } sequence.SqlQuery.QueryType = QueryType.Insert; sequence.SqlQuery.Insert.WithIdentity = methodCall.Method.Name == "InsertWithIdentity"; return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Insert.WithIdentity)); }
protected override SequenceConvertInfo Convert( ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) { return(null); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsQueryable("Insert", "InsertWithIdentity")); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsQueryable(MethodNames)); }
public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo) { return(Find(builder, buildInfo, (n, _) => n > 0)); }
static T Find <T>(ExpressionBuilder builder, BuildInfo buildInfo, Func <int, IBuildContext, T> action) { var expression = buildInfo.Expression; switch (expression.NodeType) { case ExpressionType.Constant: { var c = (ConstantExpression)expression; if (c.Value is IQueryable) { return(action(1, null)); } break; } case ExpressionType.Call: { var mc = (MethodCallExpression)expression; if (mc.Method.Name == "GetTable") { if (expression.Type.IsGenericType && expression.Type.GetGenericTypeDefinition() == typeof(Table <>)) { return(action(2, null)); } } break; } case ExpressionType.MemberAccess: if (expression.Type.IsGenericType && expression.Type.GetGenericTypeDefinition() == typeof(Table <>)) { return(action(3, null)); } // Looking for association. // if (buildInfo.IsSubQuery && buildInfo.SqlQuery.From.Tables.Count == 0) { var ctx = builder.GetContext(buildInfo.Parent, expression); if (ctx != null) { return(action(4, ctx)); } } break; case ExpressionType.Parameter: { if (buildInfo.IsSubQuery && buildInfo.SqlQuery.From.Tables.Count == 0) { var ctx = builder.GetContext(buildInfo.Parent, expression); if (ctx != null) { return(action(4, ctx)); } } break; } } return(action(0, null)); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return methodCall.IsQueryable("TableName", "DatabaseName", "OwnerName"); }
public bool IsSequence(ExpressionBuilder builder, BuildInfo buildInfo) { return(builder.IsSequence(new BuildInfo(buildInfo, ((MethodCallExpression)buildInfo.Expression).Arguments[0]))); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); }
public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param) { return(Convert(builder, (MethodCallExpression)buildInfo.Expression, buildInfo, param)); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return methodCall.IsQueryable("DefaultIfEmpty"); }
public bool IsSequence(ExpressionBuilder builder, BuildInfo buildInfo) { return builder.IsSequence(new BuildInfo(buildInfo, ((MethodCallExpression)buildInfo.Expression).Arguments[0])); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); switch (methodCall.Arguments.Count) { case 1: // int Update<T>(this IUpdateable<T> source) break; case 2: // int Update<T>(this IQueryable<T> source, Expression<Func<T,T>> setter) { BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[1].Unwrap(), sequence, sequence.SqlQuery.Update.Items, sequence); break; } case 3: { var expr = methodCall.Arguments[1].Unwrap(); if (expr is LambdaExpression) { // int Update<T>(this IQueryable<T> source, Expression<Func<T,bool>> predicate, Expression<Func<T,T>> setter) // sequence = builder.BuildWhere(buildInfo.Parent, sequence, (LambdaExpression)methodCall.Arguments[1].Unwrap(), false); BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), sequence, sequence.SqlQuery.Update.Items, sequence); } else { // static int Update<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter) // var into = builder.BuildSequence(new BuildInfo(buildInfo, expr, new SqlQuery())); BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence.SqlQuery.Update.Items, sequence); var sql = sequence.SqlQuery; sql.Select.Columns.Clear(); foreach (var item in sql.Update.Items) { sql.Select.Columns.Add(new SqlQuery.Column(sql, item.Expression)); } sql.Update.Table = ((TableBuilder.TableContext)into).SqlTable; } break; } } sequence.SqlQuery.QueryType = QueryType.Update; return(new UpdateContext(buildInfo.Parent, sequence)); }
public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo) { return BuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]))); }
protected abstract IBuildContext BuildMethodCall (ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo);
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var isGroup = methodCall.Method.Name == "GroupJoin"; var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SqlQuery)); var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var countContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); var context = new SubQueryContext(outerContext); innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext, methodCall) : new SubQueryContext(innerContext); countContext = new SubQueryContext(countContext); var join = innerContext.SqlQuery.InnerJoin(); var sql = context.SqlQuery; sql.From.Tables[0].Joins.Add(join.JoinedTable); var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap(); context.SetAlias(selector.Parameters[0].Name); innerContext.SetAlias(selector.Parameters[1].Name); var outerKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap()); var innerKeyLambda = ((LambdaExpression)methodCall.Arguments[3].Unwrap()); var outerKeySelector = outerKeyLambda.Body.Unwrap(); var innerKeySelector = innerKeyLambda.Body.Unwrap(); var outerParent = context. Parent; var innerParent = innerContext.Parent; var countParent = countContext.Parent; var outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda); var innerKeyContext = new ExpressionContext(buildInfo.Parent, innerContext, innerKeyLambda); var countKeyContext = new ExpressionContext(buildInfo.Parent, countContext, innerKeyLambda); // Process counter. // var counterSql = ((SubQueryContext)countContext).SqlQuery; // Make join and where for the counter. // if (outerKeySelector.NodeType == ExpressionType.New) { var new1 = (NewExpression)outerKeySelector; var new2 = (NewExpression)innerKeySelector; for (var i = 0; i < new1.Arguments.Count; i++) { var arg1 = new1.Arguments[i]; var arg2 = new2.Arguments[i]; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql); } } else if (outerKeySelector.NodeType == ExpressionType.MemberInit) { var mi1 = (MemberInitExpression)outerKeySelector; var mi2 = (MemberInitExpression)innerKeySelector; for (var i = 0; i < mi1.Bindings.Count; i++) { if (mi1.Bindings[i].Member != mi2.Bindings[i].Member) throw new LinqException(string.Format("List of member inits does not match for entity type '{0}'.", outerKeySelector.Type)); var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression; var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression; BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2, countKeyContext, counterSql); } } else { BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector, countKeyContext, counterSql); } context. Parent = outerParent; innerContext.Parent = innerParent; countContext.Parent = countParent; if (isGroup) { counterSql.ParentSql = sql; counterSql.Select.Columns.Clear(); var inner = (GroupJoinSubQueryContext)innerContext; inner.Join = join.JoinedTable; inner.CounterSql = counterSql; return new GroupJoinContext(buildInfo.Parent, selector, context, inner); } return new JoinContext(buildInfo.Parent, selector, context, innerContext); }
public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo) { return(BuildMethodCall(builder, (MethodCallExpression)buildInfo.Expression, buildInfo)); }
static void BuildJoin( ExpressionBuilder builder, SqlQuery.FromClause.Join join, ExpressionContext outerKeyContext, Expression outerKeySelector, ExpressionContext innerKeyContext, Expression innerKeySelector, ExpressionContext countKeyContext, SqlQuery countSql) { var predicate = builder.ConvertObjectComparison( ExpressionType.Equal, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector); if (predicate != null) join.JoinedTable.Condition.Conditions.Add(new SqlQuery.Condition(false, predicate)); else join .Expr(builder.ConvertToSql(outerKeyContext, outerKeySelector)).Equal .Expr(builder.ConvertToSql(innerKeyContext, innerKeySelector)); predicate = builder.ConvertObjectComparison( ExpressionType.Equal, outerKeyContext, outerKeySelector, countKeyContext, innerKeySelector); if (predicate != null) countSql.Where.SearchCondition.Conditions.Add(new SqlQuery.Condition(false, predicate)); else countSql.Where .Expr(builder.ConvertToSql(outerKeyContext, outerKeySelector)).Equal .Expr(builder.ConvertToSql(countKeyContext, innerKeySelector)); }
internal static void ParseSet( ExpressionBuilder builder, BuildInfo buildInfo, LambdaExpression extract, LambdaExpression update, IBuildContext select, SqlTable table, List <SqlQuery.SetExpression> items) { var ext = extract.Body; while (ext.NodeType == ExpressionType.Convert || ext.NodeType == ExpressionType.ConvertChecked) { ext = ((UnaryExpression)ext).Operand; } if (ext.NodeType != ExpressionType.MemberAccess || ext.GetRootObject() != extract.Parameters[0]) { throw new LinqException("Member expression expected for the 'Set' statement."); } var body = (MemberExpression)ext; var member = body.Member; if (member is MethodInfo) { member = TypeHelper.GetPropertyByMethod((MethodInfo)member); } var members = body.GetMembers(); var name = members .Skip(1) .Select(ex => { var me = ex as MemberExpression; if (me == null) { return(null); } var m = me.Member; if (m is MethodInfo) { m = TypeHelper.GetPropertyByMethod((MethodInfo)m); } return(m); }) .Where(m => m != null && !TypeHelper.IsNullableValueMember(m)) .Select(m => m.Name) .Aggregate((s1, s2) => s1 + "." + s2); if (table != null && !table.Fields.ContainsKey(name)) { throw new LinqException("Member '{0}.{1}' is not a table column.", member.DeclaringType.Name, name); } var column = table != null ? table.Fields[name] : select.ConvertToSql( body, 1, ConvertFlags.Field)[0].Sql; //Expression.MakeMemberAccess(Expression.Parameter(member.DeclaringType, "p"), member), 1, ConvertFlags.Field)[0].Sql; var sp = select.Parent; var ctx = new ExpressionContext(buildInfo.Parent, select, update); var expr = builder.ConvertToSqlExpression(ctx, update.Body); builder.ReplaceParent(ctx, sp); if (expr is SqlParameter && update.Body.Type.IsEnum) { ((SqlParameter)expr).SetEnumConverter(update.Body.Type, builder.MappingSchema); } items.Add(new SqlQuery.SetExpression(column, expr)); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return methodCall.IsQueryable("Concat", "Union") && methodCall.Arguments.Count == 2; }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return methodCall.Arguments.Count == 2 && methodCall.IsQueryable("Except", "Intersect"); }
protected TableContext(ExpressionBuilder builder, SqlQuery sqlQuery) { Builder = builder; SqlQuery = sqlQuery; }
protected abstract SequenceConvertInfo Convert(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param);
protected override SequenceConvertInfo Convert( ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) { return null; }
protected override SequenceConvertInfo Convert( ExpressionBuilder builder, MethodCallExpression originalMethodCall, BuildInfo buildInfo, ParameterExpression param) { var methodCall = originalMethodCall; var selector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var info = builder.ConvertSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]), selector.Parameters[0]); if (info != null) { methodCall = (MethodCallExpression)methodCall.Convert( ex => ConvertMethod(methodCall, 0, info, selector.Parameters[0], ex)); selector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); } if (param != null && param != builder.SequenceParameter) { var list = ( from path in GetExpressions(selector.Parameters[0], param, 0, selector.Body.Unwrap()) orderby path.Level descending select path ).ToList(); if (list.Count > 0) { var plist = list.Where(e => e.Expr == selector.Parameters[0]).ToList(); if (plist.Count > 1) { list = list.Except(plist.Skip(1)).ToList(); } var p = plist.FirstOrDefault(); if (p == null) { var types = methodCall.Method.GetGenericArguments(); var mgen = methodCall.Method.GetGenericMethodDefinition(); var btype = typeof(ExpressionHoder <,>).MakeGenericType(types[0], selector.Body.Type); var fields = btype.GetFields(); var pold = selector.Parameters[0]; var psel = Expression.Parameter(types[0], pold.Name); methodCall = Expression.Call( methodCall.Object, mgen.MakeGenericMethod(types[0], btype), methodCall.Arguments[0], Expression.Lambda( Expression.MemberInit( Expression.New(btype), Expression.Bind(fields[0], psel), Expression.Bind(fields[1], selector.Body.Convert(e => e == pold ? psel : e))), psel)); selector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); param = Expression.Parameter(selector.Body.Type, param.Name); list.Add(new SequenceConvertPath { Path = param, Expr = Expression.MakeMemberAccess(param, fields[1]), Level = 1 }); var expr = Expression.MakeMemberAccess(param, fields[0]); foreach (var t in list) { t.Expr = t.Expr.Convert(ex => ex == pold ? expr : ex); } return(new SequenceConvertInfo { Parameter = param, Expression = methodCall, ExpressionsToReplace = list }); } if (info != null) { if (info.ExpressionsToReplace != null) { foreach (var path in info.ExpressionsToReplace) { path.Path = path.Path.Convert(e => e == info.Parameter ? p.Path : e); path.Expr = path.Expr.Convert(e => e == info.Parameter ? p.Path : e); path.Level += p.Level; list.Add(path); } list = list.OrderByDescending(path => path.Level).ToList(); } } if (list.Count > 1) { return(new SequenceConvertInfo { Parameter = param, Expression = methodCall, ExpressionsToReplace = list .Where(e => e != p) .Select(ei => { ei.Expr = ei.Expr.Convert(e => e == p.Expr ? p.Path : e); return ei; }) .ToList() }); } } } if (methodCall != originalMethodCall) { return new SequenceConvertInfo { Parameter = param, Expression = methodCall, } } ; return(null); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsQueryable("TableName", "DatabaseName", "OwnerName")); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var resultSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap(); if (!sequence.SqlQuery.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence); var expr = collectionSelector.Body.Unwrap(); var collectionInfo = new BuildInfo(context, expr, new SqlQuery()); var collection = builder.BuildSequence(collectionInfo); var leftJoin = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext; var sql = collection.SqlQuery; var sequenceTable = sequence.SqlQuery.From.Tables[0].Source; var newQuery = null != new QueryVisitor().Find(sql, e => e == collectionInfo.SqlQuery); var crossApply = null != new QueryVisitor().Find(sql, e => e == sequenceTable || e.ElementType == QueryElementType.SqlField && sequenceTable == ((SqlField)e).Table || e.ElementType == QueryElementType.Column && sequenceTable == ((SqlQuery.Column)e).Parent); if (collection is JoinBuilder.GroupJoinSubQueryContext) { var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin; groupJoin.SqlQuery.From.Tables[0].Joins[0].JoinType = SqlQuery.JoinType.Inner; groupJoin.SqlQuery.From.Tables[0].Joins[0].IsWeak = false; } if (!newQuery) { context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } if (!crossApply) { if (!leftJoin) { context.Collection = new SubQueryContext(collection, sequence.SqlQuery, true); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { var join = SqlQuery.OuterApply(sql); sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } } if (collection is TableBuilder.TableContext) { var table = (TableBuilder.TableContext)collection; var join = table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0 ? leftJoin ? SqlQuery.OuterApply(sql) : SqlQuery.CrossApply(sql) : leftJoin?SqlQuery.LeftJoin(sql) : SqlQuery.InnerJoin(sql); join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions); sql.Where.SearchCondition.Conditions.Clear(); var collectionParent = collection.Parent as TableBuilder.TableContext; // Association. // if (collectionParent != null && collectionInfo.IsAssociationBuilt) { var ts = (SqlQuery.TableSource) new QueryVisitor().Find(sequence.SqlQuery.From, e => { if (e.ElementType == QueryElementType.TableSource) { var t = (SqlQuery.TableSource)e; return(t.Source == collectionParent.SqlTable); } return(false); }); ts.Joins.Add(join.JoinedTable); } else { sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); } context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } else { var join = leftJoin ? SqlQuery.OuterApply(sql) : SqlQuery.CrossApply(sql); sequence.SqlQuery.From.Tables[0].Joins.Add(join.JoinedTable); context.Collection = new SubQueryContext(collection, sequence.SqlQuery, false); return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context)); } }