/// <summary> /// Visists Join clause in case of join with local collection /// </summary> private void VisitJoinWithLocalCollectionClause(JoinClause joinClause) { var type = joinClause.InnerSequence.Type; var itemType = EnumerableHelper.GetIEnumerableItemType(type); var sqlTypeName = SqlTypes.GetSqlTypeName(itemType); if (string.IsNullOrWhiteSpace(sqlTypeName)) { throw new NotSupportedException("Not supported item type for Join with local collection: " + type.Name); } var isOuter = false; var sequenceExpression = joinClause.InnerSequence; object values; var subQuery = sequenceExpression as SubQueryExpression; if (subQuery != null) { isOuter = subQuery.QueryModel.ResultOperators.OfType <DefaultIfEmptyResultOperator>().Any(); sequenceExpression = subQuery.QueryModel.MainFromClause.FromExpression; } switch (sequenceExpression.NodeType) { case ExpressionType.Constant: var constantValueType = ((ConstantExpression)sequenceExpression).Value.GetType(); if (constantValueType.IsGenericType) { isOuter = DefaultIfEmptyEnumeratorType == constantValueType.GetGenericTypeDefinition(); } values = ExpressionWalker.EvaluateEnumerableValues(sequenceExpression); break; case ExpressionType.Parameter: values = ExpressionWalker.EvaluateExpression <object>(sequenceExpression); break; default: throw new NotSupportedException("Expression not supported for Join with local collection: " + sequenceExpression); } var tableAlias = _aliases.GetTableAlias(joinClause); var fieldAlias = _aliases.GetFieldAlias(joinClause.InnerKeySelector); _builder.AppendFormat("{0} join table ({1} {2} = ?) {3} on (", isOuter ? "left outer" : "inner", fieldAlias, sqlTypeName, tableAlias); Parameters.Add(values); }
/// <summary> /// Visits IEnumerable.Contains /// </summary> private void VisitContains(QueryModel subQueryModel, ContainsResultOperator contains) { ResultBuilder.Append('('); var fromExpression = subQueryModel.MainFromClause.FromExpression; var queryable = ExpressionWalker.GetCacheQueryable(fromExpression, false); if (queryable != null) { Visit(contains.Item); ResultBuilder.Append(" IN ("); if (_visitEntireSubQueryModel) { _modelVisitor.VisitQueryModel(subQueryModel, false, true); } else { _modelVisitor.VisitQueryModel(subQueryModel); } ResultBuilder.Append(')'); } else { var inValues = ExpressionWalker.EvaluateEnumerableValues(fromExpression).ToArray(); var hasNulls = inValues.Any(o => o == null); if (hasNulls) { ResultBuilder.Append('('); } Visit(contains.Item); ResultBuilder.Append(" IN ("); AppendInParameters(inValues); ResultBuilder.Append(')'); if (hasNulls) { ResultBuilder.Append(") OR "); Visit(contains.Item); ResultBuilder.Append(" IS NULL"); } } ResultBuilder.Append(')'); }