예제 #1
0
        public static Expression <Func <Tuple, bool> > BuildFilterLambda(int startIndex, IReadOnlyList <Type> keyColumnTypes, Parameter <Tuple> keyParameter)
        {
            Expression filterExpression = null;
            var        tupleParameter   = Expression.Parameter(WellKnownOrmTypes.Tuple, "tuple");
            var        valueProperty    = WellKnownOrmTypes.ParameterOfTuple
                                          .GetProperty(nameof(Parameter <Tuple> .Value), WellKnownOrmTypes.Tuple);
            var keyValue = Expression.Property(Expression.Constant(keyParameter), valueProperty);

            for (var i = 0; i < keyColumnTypes.Count; i++)
            {
                var getValueMethod            = WellKnownMembers.Tuple.GenericAccessor.MakeGenericMethod(keyColumnTypes[i]);
                var tupleParameterFieldAccess = Expression.Call(
                    tupleParameter,
                    getValueMethod,
                    Expression.Constant(startIndex + i));
                var keyParameterFieldAccess = Expression.Call(
                    keyValue,
                    getValueMethod,
                    Expression.Constant(i));
                if (filterExpression == null)
                {
                    filterExpression = Expression.Equal(tupleParameterFieldAccess, keyParameterFieldAccess);
                }
                else
                {
                    filterExpression = Expression.And(filterExpression,
                                                      Expression.Equal(tupleParameterFieldAccess, keyParameterFieldAccess));
                }
            }
            return(FastExpression.Lambda <Func <Tuple, bool> >(filterExpression, tupleParameter));
        }
        private static MethodCallExpression AddProjectionPrefetch(Expression source, LambdaExpression projection)
        {
            var itemType       = QueryHelper.GetSequenceElementType(source.Type);
            var projectionType = projection.Body.Type;

            var wrapperType              = typeof(ProjectionWrapper <,>).MakeGenericType(itemType, projectionType);
            var wrapperItemProperty      = wrapperType.GetProperty("Item");
            var wrapperProjectedProperty = wrapperType.GetProperty("Projected");

            var wrapperProjectionParameter = projection.Parameters[0];
            var wrapperProjectionLambda    = FastExpression.Lambda(
                Expression.MemberInit(
                    Expression.New(wrapperType),
                    Expression.Bind(wrapperItemProperty, wrapperProjectionParameter),
                    Expression.Bind(wrapperProjectedProperty, projection.Body)
                    ),
                wrapperProjectionParameter);
            var wrapperProjection = QueryFactory.Select(source, wrapperProjectionLambda);

            var resultProjectionParameter = Expression.Parameter(wrapperType, "wrapper");
            var resultProjectionLambda    = FastExpression.Lambda(
                Expression.MakeMemberAccess(resultProjectionParameter, wrapperItemProperty),
                resultProjectionParameter);
            var resultProjection = QueryFactory.Select(wrapperProjection, resultProjectionLambda);

            return(resultProjection);
        }
        BuildMaterializer(ProjectionExpression projection, IEnumerable <Parameter <Tuple> > tupleParameters)
        {
            var tupleReader      = Expression.Parameter(typeof(RecordSetReader), "tupleReader");
            var session          = Expression.Parameter(typeof(Session), "session");
            var parameterContext = Expression.Parameter(WellKnownOrmTypes.ParameterContext, "parameterContext");

            var itemProjector                 = projection.ItemProjector;
            var materializationInfo           = itemProjector.Materialize(context, tupleParameters);
            var elementType                   = itemProjector.Item.Type;
            var materializeMethod             = MaterializationHelper.MaterializeMethodInfo.MakeGenericMethod(elementType);
            var itemMaterializerFactoryMethod =
                elementType.IsNullable()
          ? MaterializationHelper.CreateNullableItemMaterializerMethodInfo.MakeGenericMethod(
                    elementType.GetGenericArguments()[0])
          : MaterializationHelper.CreateItemMaterializerMethodInfo.MakeGenericMethod(elementType);

            var itemMaterializer = itemMaterializerFactoryMethod.Invoke(
                null, new object[] { materializationInfo.Expression, itemProjector.AggregateType });
            Expression <Func <Session, int, MaterializationContext> > materializationContextCtor =
                (s, entityCount) => new MaterializationContext(s, entityCount);
            var materializationContextExpression = materializationContextCtor
                                                   .BindParameters(session, Expression.Constant(materializationInfo.EntitiesInRow));

            Expression body = Expression.Call(
                materializeMethod,
                tupleReader,
                materializationContextExpression,
                parameterContext,
                Expression.Constant(itemMaterializer));

            var projectorExpression = FastExpression.Lambda <Func <RecordSetReader, Session, ParameterContext, object> >(
                body, tupleReader, session, parameterContext);

            return(new Materializer(projectorExpression.CachingCompile()));
        }
예제 #4
0
        public override Expression <Func <IEnumerable <Tuple> > > GetEnumerable()
        {
            var        call         = Expression.Call(Expression.Constant(enumerableFunc.Target), enumerableFunc.Method);
            MethodInfo selectMethod = WellKnownMembers.Enumerable.Select.MakeGenericMethod(typeof(TItem), typeof(Tuple));
            var        select       = Expression.Call(selectMethod, call, Expression.Constant(converter));

            return(FastExpression.Lambda <Func <IEnumerable <Tuple> > >(select));
        }
예제 #5
0
        public static LambdaExpression MakeLambda(Expression expression, TranslatorContext context)
        {
            var tupleParameter      = Expression.Parameter(typeof(Tuple), "tuple");
            var visitor             = new ExpressionMaterializer(tupleParameter, context, null, EnumerableUtils <Parameter <Tuple> > .Empty);
            var processedExpression = OwnerRemover.RemoveOwner(expression);

            return(FastExpression.Lambda(visitor.Visit(processedExpression), tupleParameter));
        }
 private static T Evaluate <T>(Expression expression)
 {
     if (expression.NodeType == ExpressionType.Constant)
     {
         return((T)((ConstantExpression)expression).Value);
     }
     return(FastExpression.Lambda <Func <T> >(expression).CachingCompile().Invoke());
 }
        public override Expression <Func <ParameterContext, IEnumerable <Tuple> > > GetEnumerable()
        {
            var paramContext = Expression.Parameter(WellKnownOrmTypes.ParameterContext, "context");
            var call         = Expression.Call(Expression.Constant(enumerableFunc.Target), enumerableFunc.Method, paramContext);
            var selectMethod = WellKnownMembers.Enumerable.Select.MakeGenericMethod(typeof(TItem), WellKnownOrmTypes.Tuple);
            var select       = Expression.Call(selectMethod, call, Expression.Constant(converter));

            return(FastExpression.Lambda <Func <ParameterContext, IEnumerable <Tuple> > >(select, paramContext));
        }
        public Expression <Func <Tuple, Tuple, bool> > Rewrite(Expression <Func <Tuple, bool> > predicate,
                                                               ColumnCollection predicateColumns, ColumnCollection currentColumns)
        {
            Initialize(predicate, predicateColumns, currentColumns);
            leftTupleParameter = Expression.Parameter(typeof(Tuple), "leftTuple");
            var visited = Visit(predicate.Body);

            return((Expression <Func <Tuple, Tuple, bool> >)FastExpression
                   .Lambda(visited, leftTupleParameter, predicate.Parameters[0]));
        }
예제 #9
0
        private MappingEntry CreateMappingEntry(Expression expression)
        {
            var tupleAccess = expression.StripCasts().AsTupleAccess();

            if (tupleAccess != null)
            {
                return(new MappingEntry(tupleAccess.GetTupleAccessArgument()));
            }
            return(new MappingEntry(FastExpression.Lambda(expression, calculatedColumnParameter)));
        }
        public Expression <Func <Tuple, bool> > CreatePredicatesConjunction(
            Expression <Func <Tuple, bool> > newPredicate, Expression <Func <Tuple, bool> > oldPredicate)
        {
            var oldParameter = oldPredicate.Parameters[0];
            var newParameter = newPredicate.Parameters[0];
            var result       = (Expression <Func <Tuple, bool> >)parameterRewriter
                               .Replace(oldPredicate, oldParameter, newParameter);

            return((Expression <Func <Tuple, bool> >)FastExpression.Lambda(Expression
                                                                           .AndAlso(result.Body, newPredicate.Body), newParameter));
        }
            public Expression <Func <ParameterContext, T> > BindToParameterContext(Expression parameterExpression)
            {
                var body       = Visit(parameterExpression);
                var resultType = typeof(T);

                if (resultType != body.Type)
                {
                    body = Expression.Convert(body, resultType);
                }
                return(FastExpression.Lambda <Func <ParameterContext, T> >(body, parameterContextArgument));
            }
예제 #12
0
        public static MaterializationInfo MakeMaterialization(ItemProjectorExpression projector, TranslatorContext context,
                                                              IEnumerable <Parameter <Tuple> > tupleParameters)
        {
            var tupleParameter = Expression.Parameter(typeof(Tuple), "tuple");
            var materializationContextParameter = Expression.Parameter(typeof(ItemMaterializationContext), "mc");
            var visitor = new ExpressionMaterializer(tupleParameter, context, materializationContextParameter, tupleParameters);
            var lambda  = FastExpression.Lambda(visitor.Visit(projector.Item), tupleParameter, materializationContextParameter);
            var count   = visitor.entityRegistry.Count;

            return(new MaterializationInfo(count, lambda));
        }
        private static Expression <Func <IEnumerable <Tuple> > > RemapRawProviderSource(Expression <Func <IEnumerable <Tuple> > > source, MapTransform mappingTransform)
        {
            var selectMethodInfo = typeof(Enumerable)
                                   .GetMethods()
                                   .Single(methodInfo => methodInfo.Name == "Select" &&
                                           methodInfo.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func <,>))
                                   .MakeGenericMethod(typeof(Tuple), typeof(Tuple));

            Func <Tuple, Tuple> selector = tuple => mappingTransform.Apply(TupleTransformType.Auto, tuple);
            var newExpression            = Expression.Call(selectMethodInfo, source.Body, Expression.Constant(selector));

            return((Expression <Func <IEnumerable <Tuple> > >)FastExpression.Lambda(newExpression));
        }
        public static void BuildFilter(IndexInfo index)
        {
            ArgumentValidator.EnsureArgumentNotNull(index, "index");
            var parameter = Expression.Parameter(WellKnownOrmTypes.Tuple, "tuple");
            var builder   = new PartialIndexFilterBuilder(index, parameter);
            var body      = builder.Visit(index.FilterExpression.Body);
            var filter    = new PartialIndexFilterInfo {
                Expression = FastExpression.Lambda(body, parameter),
                Fields     = builder.usedFields,
            };

            index.Filter = filter;
        }
        private Expression VisitQuerySingle(MethodCallExpression mc)
        {
            var returnType = mc.Method.ReturnType;

            var argument    = mc.Arguments[0];
            var queryAll    = Expression.Call(null, WellKnownMembers.Query.All.MakeGenericMethod(returnType));
            var source      = ConstructQueryable(queryAll);
            var parameter   = Expression.Parameter(returnType, "entity");
            var keyAccessor = Expression.MakeMemberAccess(parameter, WellKnownMembers.IEntityKey);
            var equility    = Expression.Equal(keyAccessor, argument);
            var lambda      = FastExpression.Lambda(equility, parameter);

            return(VisitFirstSingle(source, lambda, mc.Method, false));
        }
예제 #16
0
        public IQueryable SelectPropertySwitchingToGeneric(IQueryable queryable, string propertyName)
        {
            Type entityType   = queryable.ElementType;
            var  propertyInfo = entityType.GetProperty(propertyName);

            var parameter = Expression.Parameter(entityType, "paramName");
            var body      = Expression.MakeMemberAccess(parameter, propertyInfo);
            var lambda    = FastExpression.Lambda(body, parameter); // paramName=>paramName.Name

            var getPropertyValuesMethodInfo = typeof(MiscTest).GetMethod("SelectPropertyGeneric");
            var genericMethod = getPropertyValuesMethodInfo.MakeGenericMethod(entityType, propertyInfo.PropertyType);

            return((IQueryable)genericMethod.Invoke(null, new object[] { queryable, lambda }));
        }
        private Func <IEnumerable <Tuple>, Session, Dictionary <Parameter <Tuple>, Tuple>, ParameterContext, TResult> BuildMaterializer <TResult>(
            ProjectionExpression projection, IEnumerable <Parameter <Tuple> > tupleParameters)
        {
            var rs      = Expression.Parameter(typeof(IEnumerable <Tuple>), "rs");
            var session = Expression.Parameter(typeof(Session), "session");
            var tupleParameterBindings = Expression.Parameter(typeof(Dictionary <Parameter <Tuple>, Tuple>), "tupleParameterBindings");
            var parameterContext       = Expression.Parameter(typeof(ParameterContext), "parameterContext");

            var itemProjector       = projection.ItemProjector;
            var materializationInfo = itemProjector.Materialize(context, tupleParameters);
            var elementType         = itemProjector.Item.Type;
            var materializeMethod   = MaterializationHelper.MaterializeMethodInfo
                                      .MakeGenericMethod(elementType);
            var compileMaterializerMethod = MaterializationHelper.CompileItemMaterializerMethodInfo
                                            .MakeGenericMethod(elementType);

            var itemMaterializer = compileMaterializerMethod.Invoke(null, new[] { materializationInfo.Expression });
            Expression <Func <Session, int, MaterializationContext> > materializationContextCtor = (s, n) => new MaterializationContext(s, n);
            var materializationContextExpression = materializationContextCtor
                                                   .BindParameters(
                session,
                Expression.Constant(materializationInfo.EntitiesInRow));

            Expression body = Expression.Call(
                materializeMethod,
                rs,
                materializationContextExpression,
                parameterContext,
                Expression.Constant(itemMaterializer),
                tupleParameterBindings);

            if (projection.IsScalar)
            {
                var scalarMethodName = projection.ResultType.ToString();
                var enumerableMethod = typeof(Enumerable)
                                       .GetMethods(BindingFlags.Static | BindingFlags.Public)
                                       .First(m => m.Name == scalarMethodName && m.GetParameters().Length == 1)
                                       .MakeGenericMethod(elementType);
                body = Expression.Call(enumerableMethod, body);
            }
            body = body.Type == typeof(TResult)
        ? body
        : Expression.Convert(body, typeof(TResult));

            var projectorExpression = FastExpression.Lambda <Func <IEnumerable <Tuple>, Session, Dictionary <Parameter <Tuple>, Tuple>, ParameterContext, TResult> >(body, rs, session, tupleParameterBindings, parameterContext);

            return(projectorExpression.CachingCompile());
        }
예제 #18
0
 public void AddValues()
 {
     foreach (SetDescriptor descriptor in Descriptors)
     {
         var addContext = new AddValueContext {
             Descriptor = descriptor,
             Lambda     =
                 FastExpression.Lambda(
                     WellKnownMembers.FuncOfTArgTResultType.MakeGenericType(typeof(T), descriptor.Expression.Type),
                     descriptor.Expression,
                     descriptor.Parameter),
             Statement = Statement
         };
         descriptor.Expression.Visit(
             delegate(ParameterExpression p) {
             // ReSharper disable AccessToModifiedClosure
             if (p == descriptor.Parameter)
             {
                 // ReSharper restore AccessToModifiedClosure
                 addContext.EntityParamExists = true;
             }
             return(p);
         });
         addContext.SubqueryExists = descriptor.Expression.IsContainsQuery();
         addContext.Field          = descriptor.Field;
         if (addContext.Field.IsEntitySet)
         {
             throw new NotSupportedException("EntitySets are not supported");
         }
         if (addContext.Field.IsEntity)
         {
             AddEntityValue(addContext);
             continue;
         }
         if (!addContext.EntityParamExists && addContext.SubqueryExists)
         {
             AddComputedStaticExpression(addContext);
         }
         else if (addContext.EntityParamExists || addContext.SubqueryExists)
         {
             AddComputedExpression(addContext);
         }
         else
         {
             AddConstantValue(addContext);
         }
     }
 }
        /// <summary>
        /// Extracts the parameter.
        /// </summary>
        /// <param name="expression">The expression.</param>
        public Expression <Func <T> > ExtractParameter <T>(Expression expression)
        {
            if (expression.NodeType == ExpressionType.Lambda)
            {
                return((Expression <Func <T> >)expression);
            }
            Type type = expression.Type;

            if (type.IsValueType)
            {
                expression = Expression.Convert(expression, typeof(T));
            }
            var lambda = FastExpression.Lambda <Func <T> >(expression);

            return(lambda);
        }
        public static bool TryRewrite(LambdaExpression resultSelector,
                                      ParameterExpression sourceParameter, ParameterExpression targetParameter, out LambdaExpression result)
        {
            var parameters = resultSelector.Parameters
                             .Select(p => p == sourceParameter ? targetParameter : p)
                             .ToArray();
            var rewriter = new SelectManySelectorRewriter(sourceParameter, targetParameter);
            var body     = rewriter.Visit(resultSelector.Body);

            if (rewriter.processingFailed)
            {
                result = null;
                return(false);
            }
            result = FastExpression.Lambda(body, parameters);
            return(true);
        }
예제 #21
0
        private void AddConstantValue(AddValueContext addContext)
        {
            SqlTableColumn column = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Column.Name);
            SqlExpression  value;
            object         constant = FastExpression.Lambda(addContext.Lambda.Body).Compile().DynamicInvoke();

            if (constant == null)
            {
                value = SqlDml.Null;
            }
            else
            {
                QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(constant.GetType(), context => constant);
                parent.Bindings.Add(binding);
                value = binding.ParameterReference;
            }
            addContext.Statement.AddValue(column, value);
        }
        /// <summary>
        /// Strips <see cref="Expression.Quote"/> expressions.
        /// </summary>
        /// <param name="expression">The expression.</param>
        public static LambdaExpression StripQuotes(this Expression expression)
        {
            while (expression.NodeType == ExpressionType.Quote)
            {
                expression = ((UnaryExpression)expression).Operand;
            }
            var lambda = expression as LambdaExpression;

            if (lambda == null)
            {
                if (!typeof(LambdaExpression).IsAssignableFrom(expression.Type))
                {
                    throw new InvalidOperationException(string.Format("Unable to process expression '{0}'", expression));
                }
                var typeAs = Expression.TypeAs(expression, typeof(LambdaExpression));
                return(FastExpression.Lambda <Func <LambdaExpression> >(typeAs).CachingCompile()());
            }
            return(lambda);
        }
            public static LambdaExpression Execute(LambdaExpression expression)
            {
                // Transform lamba expression as follows:
                // if original lambda contains sequence of reference field traversals,
                // extract this traversal sequence and create lambda with it as body, otherwise return null.
                // Longest possible expression is returned.

                // Example 1: e => e.Ref.Value > 0 transforms into e => e.Foo
                // Example 2: e => e.Value transforms into null
                // Example 3: e => e.Ref1.Ref2!=null transforms into e => e.Ref1.Ref

                var extractor = new ReferenceFieldAccessExtractor();

                extractor.parameter = expression.Parameters[0];
                extractor.Visit(expression);
                return(extractor.result == null
          ? null
          : FastExpression.Lambda(extractor.result, extractor.parameter));
            }
예제 #24
0
        /// <summary>
        /// Evaluates the specified <paramref name="e"/> into <see cref="ConstantExpression"/>.
        /// </summary>
        /// <param name="e">The expression.</param>
        public static ConstantExpression Evaluate(Expression e)
        {
            if (e == null)
            {
                return(null);
            }
            if (e.NodeType == ExpressionType.Constant)
            {
                return((ConstantExpression)e);
            }
            Type type = e.Type;

            if (type.IsValueType)
            {
                e = Expression.Convert(e, typeof(object));
            }
            var lambda = FastExpression.Lambda <Func <object> >(e);
            var func   = lambda.CachingCompile();

            return(Expression.Constant(func(), type));
        }
예제 #25
0
        public IQueryable SelectPropertyBuildingExpression(IQueryable queryable, string propertyName)
        {
            Type entityType         = queryable.ElementType;
            var  propertyInfo       = entityType.GetProperty(propertyName);
            var  queryAllExpression = Expression.Constant(queryable);

            var selectMethodInfo = typeof(System.Linq.Queryable).GetMethods()
                                   .Single(methodInfo => methodInfo.Name == Xtensive.Reflection.WellKnown.Queryable.Select &&
                                           methodInfo.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2);

            var parameter = Expression.Parameter(entityType, "paramName");
            var body      = Expression.MakeMemberAccess(parameter, propertyInfo);
            var lambda    = FastExpression.Lambda(body, parameter); // paramName=>paramName.Name

            var genericSelectMethodInfo = selectMethodInfo.MakeGenericMethod(entityType, propertyInfo.PropertyType);

            var selectExpression = Expression.Call(genericSelectMethodInfo, queryAllExpression, lambda);

            return((IQueryable)FastExpression
                   .Lambda(selectExpression, EnumerableUtils <ParameterExpression> .Empty)
                   .Compile()
                   .DynamicInvoke());
        }
        private static void AddGroupByItemWrapper(GroupByQuery groupBy, List <LambdaExpression> elementProjections)
        {
            var keySelector     = groupBy.KeySelector;
            var elementSelector = groupBy.ElementSelector;

            var keyType                = keySelector.Body.Type;
            var elementType            = elementSelector.Body.Type;
            var wrapperType            = typeof(GroupByItemWrapper <,>).MakeGenericType(keyType, elementType);
            var wrapperKeyProperty     = wrapperType.GetProperty("Key");
            var wrapperElementProperty = wrapperType.GetProperty("Element");

            var projectionParameter = keySelector.Parameters[0];
            var projectionLambda    = FastExpression.Lambda(
                Expression.MemberInit(
                    Expression.New(wrapperType),
                    Expression.Bind(wrapperKeyProperty, keySelector.Body),
                    Expression.Bind(wrapperElementProperty,
                                    elementSelector.BindParameters(projectionParameter))),
                projectionParameter);

            groupBy.Source = QueryFactory.Select(groupBy.Source, projectionLambda);

            var wrapperParameter     = Expression.Parameter(wrapperType, "wrapper");
            var wrapperKeyAccess     = Expression.MakeMemberAccess(wrapperParameter, wrapperKeyProperty);
            var wrapperElementAccess = Expression.MakeMemberAccess(wrapperParameter, wrapperElementProperty);

            groupBy.KeySelector     = FastExpression.Lambda(wrapperKeyAccess, wrapperParameter);
            groupBy.ElementSelector = FastExpression.Lambda(wrapperElementAccess, wrapperParameter);

            for (int i = 0; i < elementProjections.Count; i++)
            {
                elementProjections[i] = FastExpression.Lambda(
                    elementProjections[i].BindParameters(wrapperElementAccess),
                    wrapperParameter);
            }
        }
예제 #27
0
 internal static object Invoke(this Expression expression)
 {
     return(FastExpression.Lambda(typeof(Func <>).MakeGenericType(expression.Type), expression).Compile().DynamicInvoke());
 }
예제 #28
0
        private void AddEntityValue(AddValueContext addContext)
        {
            if (addContext.EntityParamExists)
            {
                throw new NotSupportedException("Expressions with reference to updating entity are not supported");
            }
            var methodCall = addContext.Descriptor.Expression as MethodCallExpression;
            int i;

            if (methodCall != null)
            {
                if (methodCall.Method.DeclaringType == typeof(QueryEndpoint) &&
                    methodCall.Method.Name.In("Single", "SingleOrDefault"))
                {
                    object[] keys;
                    if (methodCall.Arguments[0].Type == typeof(Key) || methodCall.Arguments[0].Type.IsSubclassOf(typeof(Key)))
                    {
                        var key = (Key)methodCall.Arguments[0].Invoke();
                        keys = new object[key.Value.Count];
                        for (i = 0; i < keys.Length; i++)
                        {
                            keys[i] = key.Value.GetValue(i);
                        }
                    }
                    else
                    {
                        keys = (object[])methodCall.Arguments[0].Invoke();
                    }
                    i = -1;
                    foreach (ColumnInfo column in addContext.Field.Columns)
                    {
                        i++;
                        SqlExpression value;
                        if (keys[i] == null)
                        {
                            value = SqlDml.Null;
                        }
                        else
                        {
                            object v = keys[i];
                            QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(v.GetType(), context => v);
                            parent.Bindings.Add(binding);
                            value = binding.ParameterReference;
                        }
                        SqlTableColumn c = SqlDml.TableColumn(addContext.Statement.Table, column.Name);
                        addContext.Statement.AddValue(c, value);
                    }
                    return;
                }
                if (methodCall.Method.DeclaringType == typeof(Queryable) &&
                    methodCall.Method.Name.In("Single", "SingleOrDefault", "First", "FirstOrDefault"))
                {
                    Expression exp  = methodCall.Arguments[0];
                    TypeInfo   info = parent.GetTypeInfo(addContext.Field.ValueType);
                    if (methodCall.Arguments.Count == 2)
                    {
                        exp = Expression.Call(
                            typeof(Queryable), "Where", new[] { info.UnderlyingType }, exp, methodCall.Arguments[1]);
                    }
                    exp = Expression.Call(typeof(Queryable), "Take", new[] { info.UnderlyingType }, exp, Expression.Constant(1));
                    i   = -1;
                    foreach (FieldInfo field in
                             info.Key.Fields)
                    {
                        i++;
                        ParameterExpression p      = Expression.Parameter(info.UnderlyingType);
                        LambdaExpression    lambda =
                            FastExpression.Lambda(
                                WellKnownMembers.FuncOfTArgTResultType.MakeGenericType(info.UnderlyingType, field.ValueType),
                                Expression.MakeMemberAccess(p, field.UnderlyingProperty),
                                p);
                        IQueryable q =
                            ((IQueryProvider)parent.QueryProvider).CreateQuery(
                                Expression.Call(typeof(Queryable), "Select", new[] { info.UnderlyingType, field.ValueType }, exp, lambda));
                        QueryTranslationResult request = parent.GetRequest(field.ValueType, q);
                        parent.Bindings.AddRange(request.ParameterBindings);
                        SqlTableColumn c = SqlDml.TableColumn(addContext.Statement.Table, addContext.Field.Columns[i].Name);
                        addContext.Statement.AddValue(c, SqlDml.SubQuery((ISqlQueryExpression)request.Query));
                    }
                    return;
                }
            }
            i = -1;
            var entity = (IEntity)FastExpression.Lambda(addContext.Lambda.Body).Compile().DynamicInvoke();

            foreach (ColumnInfo column in addContext.Field.Columns)
            {
                i++;
                SqlExpression value;
                if (entity == null)
                {
                    value = SqlDml.Null;
                }
                else
                {
                    object v = entity.Key.Value.GetValue(i);
                    QueryParameterBinding binding = parent.QueryBuilder.CreateParameterBinding(v.GetType(), context => v);
                    parent.Bindings.Add(binding);
                    value = binding.ParameterReference;
                }
                SqlTableColumn c = SqlDml.TableColumn(addContext.Statement.Table, column.Name);
                addContext.Statement.AddValue(c, value);
            }
        }
 internal static object Invoke(this Expression expression)
 {
     return(FastExpression.Lambda(
                WellKnownMembers.FuncOfTResultType.MakeGenericType(expression.Type), expression).Compile().DynamicInvoke());
 }
예제 #30
0
        public static Expression CreateEntitySetQuery(Expression ownerEntity, FieldInfo field)
        {
            if (!field.IsDynamicallyDefined && !field.UnderlyingProperty.PropertyType.IsOfGenericType(WellKnownOrmTypes.EntitySetOfT))
            {
                throw Exceptions.InternalError(Strings.ExFieldMustBeOfEntitySetType, OrmLog.Instance);
            }
            if (field.IsDynamicallyDefined && !field.ValueType.IsOfGenericType(WellKnownOrmTypes.EntitySetOfT))
            {
                throw Exceptions.InternalError(Strings.ExFieldMustBeOfEntitySetType, OrmLog.Instance);
            }

            var elementType = field.ItemType;
            var association = field.Associations.Last();

            if (association.Multiplicity == Multiplicity.OneToMany)
            {
                var targetField     = association.TargetType.Fields[association.Reversed.OwnerField.Name];
                var whereParameter  = Expression.Parameter(elementType, "p");
                var expression      = BuildExpressionForFieldRecursivly(targetField, whereParameter);
                var whereExpression = Expression.Equal(
                    Expression.Property(
                        expression,
                        WellKnownMembers.IEntityKey),
                    Expression.Property(
                        ownerEntity,
                        WellKnownMembers.IEntityKey)
                    );
                return(Expression.Call(
                           WellKnownMembers.Queryable.Where.MakeGenericMethod(elementType),
                           CreateEntityQuery(elementType),
                           FastExpression.Lambda(whereExpression, whereParameter)
                           ));
            }

            var connectorType    = association.AuxiliaryType.UnderlyingType;
            var referencingField = association.IsMaster
        ? association.AuxiliaryType.Fields[WellKnown.SlaveFieldName]
        : association.AuxiliaryType.Fields[WellKnown.MasterFieldName];
            var referencedField = association.IsMaster
        ? association.AuxiliaryType.Fields[WellKnown.MasterFieldName]
        : association.AuxiliaryType.Fields[WellKnown.SlaveFieldName];

            var filterParameter  = Expression.Parameter(connectorType, "t");
            var filterExpression = Expression.Equal(
                Expression.MakeMemberAccess(
                    Expression.MakeMemberAccess(filterParameter, referencedField.UnderlyingProperty),
                    WellKnownMembers.IEntityKey),
                Expression.MakeMemberAccess(
                    ownerEntity,
                    WellKnownMembers.IEntityKey)
                );

            var outerQuery = Expression.Call(
                WellKnownMembers.Queryable.Where.MakeGenericMethod(connectorType),
                CreateEntityQuery(connectorType),
                FastExpression.Lambda(filterExpression, filterParameter)
                );

            var outerSelectorParameter = Expression.Parameter(connectorType, "o");
            var outerSelector          = FastExpression.Lambda(
                Expression.MakeMemberAccess(outerSelectorParameter, referencingField.UnderlyingProperty),
                outerSelectorParameter);
            var innerSelectorParameter = Expression.Parameter(elementType, "i");
            var innerSelector          = FastExpression.Lambda(innerSelectorParameter, innerSelectorParameter);
            var resultSelector         = FastExpression.Lambda(innerSelectorParameter, outerSelectorParameter, innerSelectorParameter);

            var innerQuery     = CreateEntityQuery(elementType);
            var joinMethodInfo = WellKnownTypes.Queryable.GetMethods()
                                 .Single(mi => mi.Name == Xtensive.Reflection.WellKnown.Queryable.Join && mi.IsGenericMethod && mi.GetParameters().Length == 5)
                                 .MakeGenericMethod(new[] {
                connectorType,
                elementType,
                outerSelector.Body.Type,
                resultSelector.Body.Type
            });

            return(Expression.Call(joinMethodInfo,
                                   outerQuery,
                                   innerQuery,
                                   outerSelector,
                                   innerSelector,
                                   resultSelector));
        }