public TableContext(ExpressionBuilder builder, BuildInfo buildInfo) { Builder = builder; Parent = buildInfo.Parent; Expression = buildInfo.Expression; SelectQuery = buildInfo.SelectQuery; var mc = (MethodCallExpression)Expression; var attr = builder.GetTableFunctionAttribute(mc.Method); if (!typeof(ITable <>).IsSameOrParentOf(mc.Method.ReturnType)) { throw new LinqException("Table function has to return Table<T>."); } OriginalType = mc.Method.ReturnType.GetGenericArgumentsEx()[0]; ObjectType = GetObjectType(); SqlTable = new SqlTable(builder.MappingSchema, ObjectType); EntityDescriptor = Builder.MappingSchema.GetEntityDescriptor(ObjectType); SelectQuery.From.Table(SqlTable); var args = mc.Arguments.Select(a => builder.ConvertToSql(this, a)); attr.SetTable(SqlTable, mc.Method, mc.Arguments, args); Init(); }
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 (typeof(ITable <>).IsSameOrParentOf(expression.Type)) { return(action(2, null)); } } var attr = builder.GetTableFunctionAttribute(mc.Method); if (attr != null) { return(action(5, null)); } break; } case ExpressionType.MemberAccess: if (typeof(ITable <>).IsSameOrParentOf(expression.Type)) { return(action(3, null)); } // Looking for association. // if (buildInfo.IsSubQuery && buildInfo.SelectQuery.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.SelectQuery.From.Tables.Count == 0) { var ctx = builder.GetContext(buildInfo.Parent, expression); if (ctx != null) { return(action(4, ctx)); } } break; } } return(action(0, null)); }
static BuildContextType FindBuildContext(ExpressionBuilder builder, BuildInfo buildInfo, out IBuildContext?parentContext) { parentContext = null; var expression = buildInfo.Expression; switch (expression.NodeType) { case ExpressionType.Constant: { var c = (ConstantExpression)expression; if (c.Value is IQueryable queryable) { if (typeof(CteTable <>).IsSameOrParentOf(c.Value.GetType())) { return(BuildContextType.CteConstant); } // Avoid collision with ArrayBuilder var elementType = queryable.ElementType; if (builder.MappingSchema.IsScalarType(elementType) && typeof(EnumerableQuery <>).IsSameOrParentOf(c.Value.GetType())) { break; } if (queryable.Expression.NodeType == ExpressionType.NewArrayInit) { break; } return(BuildContextType.TableConstant); } break; } case ExpressionType.Call: { var mc = (MethodCallExpression)expression; switch (mc.Method.Name) { case "GetTable": { if (typeof(ITable <>).IsSameOrParentOf(expression.Type)) { return(BuildContextType.GetTableMethod); } break; } case "AsCte": return(BuildContextType.AsCteMethod); case "FromSql": return(BuildContextType.FromSqlMethod); case "FromSqlScalar": return(BuildContextType.FromSqlScalarMethod); } var attr = builder.GetTableFunctionAttribute(mc.Method); if (attr != null) { return(BuildContextType.TableFunctionAttribute); } if (mc.IsAssociation(builder.MappingSchema)) { parentContext = builder.GetContext(buildInfo.Parent, expression); if (parentContext != null) { return(BuildContextType.Association); } } break; } case ExpressionType.MemberAccess: if (typeof(ITable <>).IsSameOrParentOf(expression.Type)) { return(BuildContextType.MemberAccess); } // Looking for association. // if (buildInfo.IsSubQuery /* && buildInfo.SelectQuery.From.Tables.Count == 0*/) { parentContext = builder.GetContext(buildInfo.Parent, expression); if (parentContext != null) { return(BuildContextType.Association); } } break; case ExpressionType.Parameter: { if (buildInfo.IsSubQuery && buildInfo.SelectQuery.From.Tables.Count == 0) { // It should be handled by GroupByElementBuilder // if (typeof(IGrouping <,>).IsSameOrParentOf(expression.Type)) { break; } parentContext = builder.GetContext(buildInfo.Parent, expression); if (parentContext != null) { return(BuildContextType.Association); } } break; } } return(BuildContextType.None); }
static BuildContextType FindBuildContext(ExpressionBuilder builder, BuildInfo buildInfo, out IBuildContext parentContext) { parentContext = null; var expression = buildInfo.Expression; switch (expression.NodeType) { case ExpressionType.Constant: { var c = (ConstantExpression)expression; if (c.Value is IQueryable) { if (typeof(CteTable <>).IsSameOrParentOf(c.Value.GetType())) { return(BuildContextType.CteConstant); } return(BuildContextType.TableConstant); } break; } case ExpressionType.Call: { var mc = (MethodCallExpression)expression; switch (mc.Method.Name) { case "GetTable": if (typeof(ITable <>).IsSameOrParentOf(expression.Type)) { return(BuildContextType.GetTableMethod); } break; case "AsCte": return(BuildContextType.AsCteMethod); } var attr = builder.GetTableFunctionAttribute(mc.Method); if (attr != null) { return(BuildContextType.TableFunctionAttribute); } if (mc.IsAssociation(builder.MappingSchema)) { parentContext = builder.GetContext(buildInfo.Parent, expression); if (parentContext != null) { return(BuildContextType.Association); } } break; } case ExpressionType.MemberAccess: if (typeof(ITable <>).IsSameOrParentOf(expression.Type)) { return(BuildContextType.MemberAccess); } // Looking for association. // if (buildInfo.IsSubQuery && buildInfo.SelectQuery.From.Tables.Count == 0) { parentContext = builder.GetContext(buildInfo.Parent, expression); if (parentContext != null) { return(BuildContextType.Association); } } break; case ExpressionType.Parameter: { if (buildInfo.IsSubQuery && buildInfo.SelectQuery.From.Tables.Count == 0) { parentContext = builder.GetContext(buildInfo.Parent, expression); if (parentContext != null) { return(BuildContextType.Association); } } break; } } return(BuildContextType.None); }