TableBuilder.TableContext GetTableContext(IBuildContext ctx, Expression path, out Expression?stopExpression) { stopExpression = null; var table = ctx as TableBuilder.TableContext; if (table != null) { return(table); } if (ctx is LoadWithContext lwCtx) { return(lwCtx.TableContext); } if (table == null) { var isTableResult = ctx.IsExpression(null, 0, RequestFor.Table); if (isTableResult.Result) { table = isTableResult.Context as TableBuilder.TableContext; if (table != null) { return(table); } } } var maxLevel = path.GetLevel(ctx.Builder.MappingSchema); var level = 1; while (level <= maxLevel) { var levelExpression = path.GetLevelExpression(ctx.Builder.MappingSchema, level); var isTableResult = ctx.IsExpression(levelExpression, 1, RequestFor.Table); if (isTableResult.Result) { table = isTableResult.Context switch { TableBuilder.TableContext t => t, AssociationContext a => a.TableContext as TableBuilder.TableContext, _ => null }; if (table != null) { stopExpression = levelExpression; return(table); } } ++level; } var expr = path.GetLevelExpression(ctx.Builder.MappingSchema, 0); throw new LinqToDBException( $"Unable to find table information for LoadWith. Consider moving LoadWith closer to GetTable<{expr.Type.Name}>() method."); }
public static TableBuilder.TableContext?GetTableContext(IBuildContext context) { var table = context as TableBuilder.TableContext; if (table != null) { return(table); } if (context is LoadWithBuilder.LoadWithContext lwCtx) { return(lwCtx.TableContext); } if (table == null) { var isTableResult = context.IsExpression(null, 0, RequestFor.Table); if (isTableResult.Result) { table = isTableResult.Context as TableBuilder.TableContext; if (table != null) { return(table); } } } return(null); }
static void BuildSetter( ExpressionBuilder builder, IBuildContext into, List <SelectQuery.SetExpression> items, IBuildContext ctx, MemberInitExpression expression, Expression path) { foreach (var binding in expression.Bindings) { var member = binding.Member; if (member is MethodInfo) { member = ((MethodInfo)member).GetPropertyInfo(); } if (binding is MemberAssignment) { var ma = binding as MemberAssignment; var pe = Expression.MakeMemberAccess(path, member); if (ma.Expression is MemberInitExpression && !into.IsExpression(pe, 1, RequestFor.Field).Result) { BuildSetter( builder, into, items, ctx, (MemberInitExpression)ma.Expression, Expression.MakeMemberAccess(path, member)); } else { var column = into.ConvertToSql(pe, 1, ConvertFlags.Field); var expr = builder.ConvertToSqlExpression(ctx, ma.Expression); if (expr.ElementType == QueryElementType.SqlParameter) { var parm = (SqlParameter)expr; var field = column[0].Sql is SqlField ? (SqlField)column[0].Sql : (SqlField)((SelectQuery.Column)column[0].Sql).Expression; if (parm.DataType == DataType.Undefined) { parm.DataType = field.DataType; } } items.Add(new SelectQuery.SetExpression(column[0].Sql, expr)); } } else { throw new InvalidOperationException(); } } }
public bool IsExpression(Expression expression, int level, RequestFor testFlag) { switch (testFlag) { case RequestFor.SubQuery: return(true); } return(SubQuery.IsExpression(expression, level, testFlag)); }
static void BuildSetter( ExpressionBuilder builder, IBuildContext into, List <SqlQuery.SetExpression> items, IBuildContext ctx, MemberInitExpression expression, Expression path) { foreach (var binding in expression.Bindings) { var member = binding.Member; if (member is MethodInfo) { member = TypeHelper.GetPropertyByMethod((MethodInfo)member); } if (binding is MemberAssignment) { var ma = binding as MemberAssignment; var pe = Expression.MakeMemberAccess(path, member); if (ma.Expression is MemberInitExpression && !into.IsExpression(pe, 1, RequestFor.Field).Result) { BuildSetter( builder, into, items, ctx, (MemberInitExpression)ma.Expression, Expression.MakeMemberAccess(path, member)); } else { var column = into.ConvertToSql(pe, 1, ConvertFlags.Field); var expr = builder.ConvertToSqlExpression(ctx, ma.Expression, false); if (expr is SqlValueBase && TypeHelper.IsEnumOrNullableEnum(ma.Expression.Type)) { var memberAccessor = TypeAccessor.GetAccessor(ma.Member.DeclaringType)[ma.Member.Name]; ((SqlValueBase)expr).SetEnumConverter(memberAccessor, builder.MappingSchema); } items.Add(new SqlQuery.SetExpression(column[0].Sql, expr)); } } else { throw new InvalidOperationException(); } } }
TableBuilder.TableContext?GetTableContext(IBuildContext ctx) { var table = ctx as TableBuilder.TableContext; if (table == null) { var isTableResult = ctx.IsExpression(null, 0, RequestFor.Table); if (isTableResult.Result) { table = isTableResult.Context as TableBuilder.TableContext; } } return(table); }
static void BuildSetter( ExpressionBuilder builder, IBuildContext into, List <SqlQuery.SetExpression> items, IBuildContext ctx, MemberInitExpression expression, Expression path) { foreach (var binding in expression.Bindings) { var member = binding.Member; if (member is MethodInfo) { member = ((MethodInfo)member).GetPropertyInfo(); } if (binding is MemberAssignment) { var ma = binding as MemberAssignment; var pe = Expression.MakeMemberAccess(path, member); if (ma.Expression is MemberInitExpression && !into.IsExpression(pe, 1, RequestFor.Field).Result) { BuildSetter( builder, into, items, ctx, (MemberInitExpression)ma.Expression, Expression.MakeMemberAccess(path, member)); } else { var column = into.ConvertToSql(pe, 1, ConvertFlags.Field); var expr = builder.ConvertToSqlExpression(ctx, ma.Expression); items.Add(new SqlQuery.SetExpression(column[0].Sql, expr)); } } else { throw new InvalidOperationException(); } } }
void CheckAndAddMember(IBuildContext sequence1, IBuildContext sequence2, SqlInfo info) { var member = new Member { SequenceInfo = info, MemberExpression = Expression.PropertyOrField(_unionParameter, info.Members[0].Name) }; if (sequence1.IsExpression(member.MemberExpression, 1, RequestFor.Object).Result) { throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name); } var idx = sequence2.ConvertToIndex(member.MemberExpression, 1, ConvertFlags.Field); if (idx[0].Index != member.SequenceInfo.Index) { throw new LinqException("Types in {0} are constructed incompatibly.", _methodCall.Method.Name); } _members.Add(member.MemberExpression.Member, member); }
public Expression BuildMultipleQuery(IBuildContext context, Expression expression) { if (!Common.Configuration.Linq.AllowMultipleQuery) { throw new LinqException("Multiple queries are not allowed. Set the 'LinqToDB.Common.Configuration.Linq.AllowMultipleQuery' flag to 'true' to allow multiple queries."); } var parameters = new HashSet <ParameterExpression>(); expression.Visit(e => { if (e.NodeType == ExpressionType.Lambda) { foreach (var p in ((LambdaExpression)e).Parameters) { parameters.Add(p); } } }); // Convert associations. // expression = expression.Transform(e => { switch (e.NodeType) { case ExpressionType.MemberAccess: { var root = e.GetRootObject(); if (root != null && root.NodeType == ExpressionType.Parameter && !parameters.Contains((ParameterExpression)root)) { var res = context.IsExpression(e, 0, RequestFor.Association); if (res.Result) { var table = (TableBuilder.AssociatedTableContext)res.Context; if (table.IsList) { var ttype = typeof(Table <>).MakeGenericType(table.ObjectType); var tbl = Activator.CreateInstance(ttype); var method = typeof(LinqExtensions) .GetMethod("Where", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static) .MakeGenericMethod(e.Type, table.ObjectType, ttype); var me = (MemberExpression)e; var op = Expression.Parameter(table.ObjectType, "t"); parameters.Add(op); Expression ex = null; for (var i = 0; i < table.Association.ThisKey.Length; i++) { var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]]; var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]]; var ee = Expression.Equal( Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo), Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo)); ex = ex == null ? ee : Expression.AndAlso(ex, ee); } return(Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op))); } } } break; } } return(e); }); var paramex = Expression.Parameter(typeof(object[]), "ps"); var parms = new List <Expression>(); // Convert parameters. // expression = expression.Transform(e => { var root = e.GetRootObject(); if (root != null && root.NodeType == ExpressionType.Parameter && !parameters.Contains((ParameterExpression)root)) { var ex = Expression.Convert(BuildExpression(context, e), typeof(object)); parms.Add(ex); return(Expression.Convert( Expression.ArrayIndex(paramex, Expression.Constant(parms.Count - 1)), e.Type)); } return(e); }); var sqtype = typeof(MultipleQueryHelper <>).MakeGenericType(expression.Type); var helper = (IMultipleQueryHelper)Activator.CreateInstance(sqtype); return(helper.GetSubquery(this, expression, paramex, parms)); }
static Expression GetMultipleQueryExpression(IBuildContext context, MappingSchema mappringSchema, Expression expression, HashSet <ParameterExpression> parameters) { if (!Common.Configuration.Linq.AllowMultipleQuery) { throw new LinqException("Multiple queries are not allowed. Set the 'LinqToDB.Common.Configuration.Linq.AllowMultipleQuery' flag to 'true' to allow multiple queries."); } expression.Visit(e => { if (e.NodeType == ExpressionType.Lambda) { foreach (var p in ((LambdaExpression)e).Parameters) { parameters.Add(p); } } }); // Convert associations. // return(expression.Transform(e => { switch (e.NodeType) { case ExpressionType.MemberAccess: { var root = e.GetRootObject(); if (root != null && root.NodeType == ExpressionType.Parameter && !parameters.Contains((ParameterExpression)root)) { var res = context.IsExpression(e, 0, RequestFor.Association); if (res.Result) { var table = (TableBuilder.AssociatedTableContext)res.Context; if (table.IsList) { var ttype = typeof(Table <>).MakeGenericType(table.ObjectType); var tbl = Activator.CreateInstance(ttype, context.Builder.DataContext); var method = e == expression ? MemberHelper.MethodOf <IEnumerable <bool> >(n => n.Where(a => a)).GetGenericMethodDefinition().MakeGenericMethod(table.ObjectType) : _whereMethodInfo.MakeGenericMethod(e.Type, table.ObjectType, ttype); var me = (MemberExpression)e; var op = Expression.Parameter(table.ObjectType, "t"); parameters.Add(op); Expression ex = null; for (var i = 0; i < table.Association.ThisKey.Length; i++) { var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]]; var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]]; var ma1 = Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo); var ma2 = Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo); var ee = Equal(mappringSchema, ma1, ma2); ex = ex == null ? ee : Expression.AndAlso(ex, ee); } var expr = Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op)); if (e == expression) { expr = Expression.Call( MemberHelper.MethodOf <IEnumerable <int> >(n => n.ToList()).GetGenericMethodDefinition().MakeGenericMethod(table.ObjectType), expr); } return expr; } } } break; } } return e; })); }
static Expression GetMultipleQueryExpressionLazy(IBuildContext context, MappingSchema mappingSchema, Expression expression, HashSet <ParameterExpression> parameters) { expression.Visit(e => { if (e.NodeType == ExpressionType.Lambda) { foreach (var p in ((LambdaExpression)e).Parameters) { parameters.Add(p); } } }); // Convert associations. // return(expression.Transform(e => { switch (e.NodeType) { case ExpressionType.MemberAccess : { var root = e.GetRootObject(mappingSchema); if (root != null && root.NodeType == ExpressionType.Parameter && !parameters.Contains((ParameterExpression)root)) { var res = context.IsExpression(e, 0, RequestFor.Association); if (res.Result) { var table = (TableBuilder.AssociatedTableContext)res.Context !; if (table.IsList) { var me = (MemberExpression)e; Expression expr; var parentType = me.Expression.Type; var childType = table.ObjectType; var queryMethod = table.Association.GetQueryMethod(parentType, childType); if (queryMethod != null) { //TODO: MARS var dcConst = Expression.Constant(context.Builder.DataContext.Clone(true)); expr = queryMethod.GetBody(me.Expression, dcConst); } else { var ttype = typeof(Table <>).MakeGenericType(childType); var tbl = Activator.CreateInstance(ttype, context.Builder.DataContext); var method = e == expression ? MemberHelper.MethodOf <IEnumerable <bool> >(n => n.Where(a => a)).GetGenericMethodDefinition().MakeGenericMethod(childType) : _whereMethodInfo.MakeGenericMethod(e.Type, childType, ttype); var op = Expression.Parameter(childType, "t"); parameters.Add(op); Expression?ex = null; for (var i = 0; i < table.Association.ThisKey.Length; i++) { var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]]; var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]]; var ma1 = Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo); var ma2 = Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo); var ee = Equal(mappingSchema, ma1, ma2); ex = ex == null ? ee : Expression.AndAlso(ex, ee); } var predicate = table.Association.GetPredicate(parentType, childType); if (predicate != null) { var body = predicate.GetBody(me.Expression, op); ex = ex == null ? body : Expression.AndAlso(ex, body); } if (ex == null) { throw new LinqToDBException($"Invalid association configuration for {table.Association.MemberInfo.DeclaringType}.{table.Association.MemberInfo.Name}"); } expr = Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op)); } if (e == expression) { expr = Expression.Call( MemberHelper.MethodOf <IEnumerable <int> >(n => n.ToList()).GetGenericMethodDefinition().MakeGenericMethod(childType), expr); } return expr; } } } break; } } return e; })); }
static Expression GetMultipleQueryExpressionLazy(IBuildContext context, MappingSchema mappingSchema, Expression expression, HashSet <ParameterExpression> parameters) { expression.Visit(e => { if (e.NodeType == ExpressionType.Lambda) { foreach (var p in ((LambdaExpression)e).Parameters) { parameters.Add(p); } } }); // Convert associations. // return(expression.Transform(e => { switch (e.NodeType) { case ExpressionType.MemberAccess : { var root = context.Builder.GetRootObject(e); if (root != null && root.NodeType == ExpressionType.Parameter && !parameters.Contains((ParameterExpression)root)) { var res = context.IsExpression(e, 0, RequestFor.Association); if (res.Result) { var associationContext = (AssociationContext)res.Context !; if (associationContext.Descriptor.IsList) { var me = (MemberExpression)e; var parentType = me.Expression.Type; var childType = me.Type; var queryMethod = AssociationHelper.CreateAssociationQueryLambda(context.Builder, new AccessorMember(me), associationContext.Descriptor, parentType, parentType, childType, false, false, null, out _); var dcConst = Expression.Constant(context.Builder.DataContext.Clone(true)); var expr = queryMethod.GetBody(me.Expression, dcConst); if (e == expression) { expr = Expression.Call( Methods.Enumerable.ToList.MakeGenericMethod(childType), expr); } return expr; } } } break; } } return e; })); }
public override IsExpressionResult IsExpression(Expression?expression, int level, RequestFor requestFlag) => _source.IsExpression(expression, level, requestFlag);
static Expression GetMultipleQueryExpression(IBuildContext context, MappingSchema mappingSchema, Expression expression, HashSet <ParameterExpression> parameters) { if (!Common.Configuration.Linq.AllowMultipleQuery) { throw new LinqException("Multiple queries are not allowed. Set the 'LinqToDB.Common.Configuration.Linq.AllowMultipleQuery' flag to 'true' to allow multiple queries."); } expression.Visit(e => { if (e.NodeType == ExpressionType.Lambda) { foreach (var p in ((LambdaExpression)e).Parameters) { parameters.Add(p); } } }); // Convert associations. // return(expression.Transform(e => { switch (e.NodeType) { case ExpressionType.MemberAccess: { var root = e.GetRootObject(mappingSchema); if (root != null && root.NodeType == ExpressionType.Parameter && !parameters.Contains((ParameterExpression)root)) { var res = context.IsExpression(e, 0, RequestFor.Association); if (res.Result) { var table = (TableBuilder.AssociatedTableContext)res.Context; if (table.IsList) { var me = (MemberExpression)e; Expression expr; var parentType = me.Expression.Type; var childType = table.ObjectType; var queryMethod = table.Association.GetQueryMethod(parentType, childType); if (queryMethod != null) { var parentParam = Expression.Parameter(parentType, "o"); var ptype = typeof(Table <>).MakeGenericType(parentType); var ptbl = Activator.CreateInstance(ptype, context.Builder.DataContext); var principalExpression = Expression.Constant(ptbl); var selectMany = (MethodCallExpression)table.GetAssociationQueryExpression(Expression.Constant(context.Builder.DataContext), null, parentType, principalExpression, queryMethod); var parentDescriptor = mappingSchema.GetEntityDescriptor(parentType); var keyColumns = parentDescriptor.Columns.Where(c => c.IsPrimaryKey).ToList(); if (keyColumns.Count == 0) { keyColumns = parentDescriptor.Columns; } var arguments = selectMany.Arguments.ToList(); Expression predicate = null; foreach (var column in keyColumns) { var ee = Expression.Equal( Expression.MakeMemberAccess( parentParam, column.MemberInfo), Expression.MakeMemberAccess( root, column.MemberInfo)); predicate = predicate == null ? ee : Expression.AndAlso(predicate, ee); } if (predicate == null) { throw new LinqToDBException($"Invalid mapping for Principal Entity during association building. Association {table.Association.MemberInfo.DeclaringType}.{table.Association.MemberInfo.Name}"); } var filteredQuery = Expression.Call(null, _queryableMethodInfo.MakeGenericMethod(parentType), arguments[0], Expression.Lambda(predicate, parentParam)); arguments[0] = filteredQuery; selectMany = selectMany.Update(selectMany.Object, arguments); var asQueryable = MemberHelper .MethodOf((IQueryable <object> q) => LinqExtensions.AsQueryable <object, object>(0)) .GetGenericMethodDefinition() .MakeGenericMethod(e.Type, selectMany.Type); expr = Expression.Call(null, asQueryable, selectMany); } else { var ttype = typeof(Table <>).MakeGenericType(childType); var tbl = Activator.CreateInstance(ttype, context.Builder.DataContext); var method = e == expression ? MemberHelper.MethodOf <IEnumerable <bool> >(n => n.Where(a => a)).GetGenericMethodDefinition().MakeGenericMethod(childType) : _whereMethodInfo.MakeGenericMethod(e.Type, childType, ttype); var op = Expression.Parameter(childType, "t"); parameters.Add(op); Expression ex = null; for (var i = 0; i < table.Association.ThisKey.Length; i++) { var field1 = table.ParentAssociation.SqlTable.Fields[table.Association.ThisKey [i]]; var field2 = table.SqlTable.Fields[table.Association.OtherKey[i]]; var ma1 = Expression.MakeMemberAccess(op, field2.ColumnDescriptor.MemberInfo); var ma2 = Expression.MakeMemberAccess(me.Expression, field1.ColumnDescriptor.MemberInfo); var ee = Equal(mappingSchema, ma1, ma2); ex = ex == null ? ee : Expression.AndAlso(ex, ee); } var predicate = table.Association.GetPredicate(parentType, childType); if (predicate != null) { var body = predicate.GetBody(me.Expression, op); ex = ex == null ? body : Expression.AndAlso(ex, body); } if (ex == null) { throw new LinqToDBException($"Invalid association configuration for {table.Association.MemberInfo.DeclaringType}.{table.Association.MemberInfo.Name}"); } expr = Expression.Call(null, method, Expression.Constant(tbl), Expression.Lambda(ex, op)); } if (e == expression) { expr = Expression.Call( MemberHelper.MethodOf <IEnumerable <int> >(n => n.ToList()).GetGenericMethodDefinition().MakeGenericMethod(childType), expr); } return expr; } } } break; } } return e; })); }