/// <summary> /// Creates a <see cref="ICriterion" /> for a binary operation. /// </summary> /// <param name="a"> /// Expression A. /// </param> /// <param name="b"> /// Expression B. /// </param> /// <param name="type"> /// The operation type. /// </param> /// <param name="context"> /// The helper context. /// </param> /// <returns> /// The created <see cref="ICriterion" />. /// </returns> public static ICriterion GetCriterionForBinary ( Expression a, Expression b, ExpressionType type, HelperContext context ) { if (a.NodeType == ExpressionType.Convert) { return(GetCriterionForBinary(((UnaryExpression)a).Operand, b, type, context)); } if (b.NodeType == ExpressionType.Convert) { return(GetCriterionForBinary(a, ((UnaryExpression)b).Operand, type, context)); } switch (type) { case ExpressionType.AndAlso: return(Restrictions.And(GetCriterion(a, context), GetCriterion(b, context))); case ExpressionType.OrElse: return(Restrictions.Or(GetCriterion(a, context), GetCriterion(b, context))); case ExpressionType.ExclusiveOr: ICriterion criterionA = GetCriterion(a, context); ICriterion criterionB = GetCriterion(b, context); return(Restrictions .Or ( Restrictions.And(criterionA, Restrictions.Not(criterionB)), Restrictions.And(criterionB, Restrictions.Not(criterionA)) )); } bool isProjectedA = IsProjected(a, context); bool isProjectedB = IsProjected(b, context); // Projection-Projection if (isProjectedA && isProjectedB) { return(GetProjectionProjectionCriterion ( ProjectionHelper.GetProjection(a, context), ProjectionHelper.GetProjection(b, context), type )); } if (isProjectedA || !isProjectedB) { return(GetProjectionValueCriterion(a, ExpressionHelper.GetValue(b), type, context, false)); } return(GetProjectionValueCriterion(b, ExpressionHelper.GetValue(a), type, context, true)); }
/// <summary> /// Generates new orders based on the underlying source by resolving the appropriate projections from the /// given lambda expression. /// </summary> /// <param name="orderByStatements"> /// The order by statements. /// </param> /// <param name="projection"> /// The projection. /// </param> /// <param name="data"> /// The helper data. /// </param> /// <returns> /// The new set of orders. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="orderByStatements" />, <paramref name="projection" /> or <paramref name="data" /> is /// null. /// </exception> public static IEnumerable <OrderByStatement> GetSourceBasedOrdersFrom ( IEnumerable <OrderByStatement> orderByStatements, LambdaExpression projection, QueryHelperData data ) { if (orderByStatements == null) { throw new ArgumentNullException("orderByStatements"); } if (projection == null) { throw new ArgumentNullException("projection"); } if (data == null) { throw new ArgumentNullException("data"); } if (orderByStatements.All(x => x.IsBasedOnSource)) { return(orderByStatements); } ProjectionHelper.GetProjection(projection, new HelperContext(data, projection, HelperType.Select)); var orders = new List <OrderByStatement>(); foreach (var statement in orderByStatements) { if (statement.IsBasedOnSource) { orders.Add(statement); continue; } IProjection orderProjection; bool foundMapping = data.Mappings .TryGetValue(statement.Property, out orderProjection); if (foundMapping) { var order = new OrderByStatement { IsBasedOnSource = true, Order = new Order(orderProjection, statement.OrderAscending) }; orders.Add(order); } } return(orders); }
/// <summary> /// Creates <see cref="ICriterion" /> for a comparison between a value and a projection. /// </summary> /// <param name="expression"> /// The expression. /// </param> /// <param name="value"> /// The value. /// </param> /// <param name="type"> /// The comparison type. /// </param> /// <param name="context"> /// The helper context. /// </param> /// <param name="overTurned"> /// Indicates whether the comparison has been reversed to simplify other code. /// </param> /// <returns> /// The created <see cref="ICriterion" />. /// </returns> /// <exception cref="NotSupportedException"> /// The <see cref="Expression" /> could not be resolved as it may contain unsupported features or similar. /// </exception> public static ICriterion GetProjectionValueCriterion ( Expression expression, object value, ExpressionType type, HelperContext context, bool overTurned ) { if (overTurned) { switch (type) { case ExpressionType.GreaterThan: type = ExpressionType.LessThan; break; case ExpressionType.GreaterThanOrEqual: type = ExpressionType.LessThanOrEqual; break; case ExpressionType.LessThan: type = ExpressionType.GreaterThan; break; case ExpressionType.LessThanOrEqual: type = ExpressionType.GreaterThanOrEqual; break; } } IProjection projection = ProjectionHelper.GetProjection(expression, context); switch (type) { case ExpressionType.Equal: if (value == null) { return(Restrictions.IsNull(projection)); } if (value is bool) { return(GetCriterion((bool)value ? expression : Expression.Not(expression), context)); } return(Restrictions.Eq(projection, value)); case ExpressionType.NotEqual: if (value == null) { return(Restrictions.IsNotNull(projection)); } if (value is bool) { return(GetCriterion(!(bool)value ? expression : Expression.Not(expression), context)); } return(Restrictions.Not(Restrictions.Eq(projection, value))); case ExpressionType.GreaterThan: return(Restrictions.Gt(projection, value)); case ExpressionType.GreaterThanOrEqual: return(Restrictions.Ge(projection, value)); case ExpressionType.LessThan: return(Restrictions.Lt(projection, value)); case ExpressionType.LessThanOrEqual: return(Restrictions.Le(projection, value)); default: throw new NotSupportedException ( "the expression contains unsupported features, please revise your code" ); } }
/// <summary> /// Creates a <see cref="ICriterion" /> for the given <see cref="MethodCallExpression" />. /// </summary> /// <param name="expression"> /// The expression. /// </param> /// <param name="context"> /// The helper context. /// </param> /// <returns> /// The created <see cref="ICriterion" />. /// </returns> public static ICriterion GetCriterionForMethodCall ( MethodCallExpression expression, HelperContext context ) { if (IsProjected(expression, context)) { // Not a value expression IProjection projection = ProjectionHelper .GetProjection ( expression.Object ?? expression.Arguments[0], context ); int i = expression.Object == null ? 1 : 0; switch (expression.Method.Name) { case "In": case "IsIn": object value = ExpressionHelper.GetValue(expression.Arguments[i]); if (!(value is ICollection)) { if (value is IEnumerable) { var objs = new List <object>(); foreach (object obj in value as IEnumerable) { objs.Add(obj); } return(Restrictions .In ( projection, objs.ToArray() )); } if (value is IDetachedImmutableFlowQuery) { return(Subqueries .PropertyIn ( ExpressionHelper.GetPropertyName(expression, context.RootAlias), (value as IDetachedImmutableFlowQuery).Criteria )); } } return(Restrictions .In ( projection, value as ICollection )); case "Between": case "IsBetween": return(Restrictions .Between ( projection, ExpressionHelper.GetValue(expression.Arguments[i]), ExpressionHelper.GetValue(expression.Arguments[i + 1]) )); case "Like": case "IsLike": return(GetLikeCriterion(projection, expression.Arguments[i], MatchMode.Exact)); case "StartsWith": return(GetLikeCriterion(projection, expression.Arguments[i], MatchMode.Start)); case "EndsWith": return(GetLikeCriterion(projection, expression.Arguments[i], MatchMode.End)); case "Contains": return(GetLikeCriterion(projection, expression.Arguments[i], MatchMode.Anywhere)); case "IsLessThan": return(Restrictions.Lt(projection, ExpressionHelper.GetValue(expression.Arguments[i]))); case "IsLessThanOrEqualTo": return(Restrictions.Le(projection, ExpressionHelper.GetValue(expression.Arguments[i]))); case "IsGreaterThan": return(Restrictions.Gt(projection, ExpressionHelper.GetValue(expression.Arguments[i]))); case "IsGreaterThanOrEqualTo": return(Restrictions.Ge(projection, ExpressionHelper.GetValue(expression.Arguments[i]))); case "IsEqualTo": return(Restrictions.Eq(projection, ExpressionHelper.GetValue(expression.Arguments[i]))); case "IsNull": return(Restrictions.IsNull(projection)); case "IsNotNull": return(Restrictions.IsNotNull(projection)); } throw new NotSupportedException ( "The expression contains unsupported features, please revise your code" ); } return(Restrictions.Eq(Projections.Constant(ExpressionHelper.GetValue <bool>(expression)), true)); }