private string TranslateOneToMany(string functionName, MemberExpression memberExpression, LambdaExpression fieldExpression, LambdaExpression filterExpression) { if (!string.IsNullOrEmpty(TranslateMember(memberExpression))) // this shouldn't return any SQL { throw new SqlExpressionTranslatorException(memberExpression.ToString()); } var relation = GetRelation(memberExpression.Expression, memberExpression.Member.Name); if (relation == null) { throw new SqlExpressionTranslatorException(memberExpression.ToString()); } if (fieldExpression != null && filterExpression != null && fieldExpression.Parameters[0] != filterExpression.Parameters[0]) { throw new SqlExpressionTranslatorException(null); } var iterator = fieldExpression != null ? fieldExpression.Parameters[0] : filterExpression != null ? filterExpression.Parameters[0] : Expression.Parameter(relation.ElementType); LambdaExpression relationExpression = CreateToManyFilterExpression(relation, memberExpression.Expression, filterExpression, iterator); var template = _toManyTemplates[functionName]; if (template == null) { throw new NotSupportedException(functionName); } var alias = SqlNameGenerator.NextTableAlias(); _metaData[iterator] = new ExpressionMetaData { Iterator = iterator, Relation = relation, Schema = relation.ForeignSchema }; _relationAliases[iterator] = new Dictionary <object, string> { { relation, alias } }; _subQueries.Push(new SubQuery()); string sqlFields = Translate(fieldExpression); string sqlWhere = Translate(relationExpression); string sqlJoins = (Joins.Count > 0) ? string.Join(" ", Joins.Select(join => join.ToSql(_sqlDialect))) : null; _subQueries.Pop(); return(string.Format(template, sqlFields, _sqlDialect.QuoteTable(relation.ForeignSchema.MappedName) + " " + alias, sqlJoins ?? "", sqlWhere )); }
private string ProcessRelation(Expression fullExpression, Expression leftExpression, string memberName) { if (leftExpression.NodeType == ExpressionType.Convert) { leftExpression = ((UnaryExpression)leftExpression).Operand; } var parentMetaData = _metaData[leftExpression]; if (parentMetaData != null) { if (_metaData.ContainsKey(fullExpression)) { return(null); // relation already visited } var iterator = GetRootIterator(parentMetaData.Iterator); var relation = parentMetaData.Schema.Relations[memberName]; var leftAlias = _relationAliases[iterator][parentMetaData.Key]; if (relation != null && relation.IsToOne) { if (!_relationAliases[iterator].ContainsKey(relation)) { var sqlJoin = new SqlJoinDefinition( new SqlJoinPart(parentMetaData.Schema, relation.LocalField, leftAlias), new SqlJoinPart(relation.ForeignSchema, relation.ForeignField, SqlNameGenerator.NextTableAlias()) ); CurrentQuery.Joins.Add(sqlJoin); _relationAliases[iterator][relation] = sqlJoin.Right.Alias; } _metaData[fullExpression] = new ExpressionMetaData { Iterator = iterator, Relation = relation, Schema = relation.ForeignSchema }; } else if (relation == null) { return(leftAlias + "." + (_schema.FieldsByFieldName[memberName]?.MappedName ?? memberName)); } } return(null); }