// <summary>
        // Generates CQT for the current <see cref="CaseStatement" />.
        // </summary>
        internal DbExpression AsCqt(DbExpression row, IEnumerable <WithRelationship> withRelationships)
        {
            // Generate the Case WHEN .. THEN ..., WHEN ... THEN ..., END
            var conditions = new List <DbExpression>();
            var values     = new List <DbExpression>();

            foreach (var clause in Clauses)
            {
                conditions.Add(clause.Condition.AsCqt(row));
                values.Add(CaseSlotValueAsCqt(row, clause.Value, MemberPath, withRelationships));
            }

            // Generate ELSE
            var elseValue = ElseValue != null
                                ? CaseSlotValueAsCqt(row, ElseValue, MemberPath, withRelationships)
                                : Constant.Null.AsCqt(row, MemberPath);

            if (Clauses.Count > 0)
            {
                return(DbExpressionBuilder.Case(conditions, values, elseValue));
            }
            else
            {
                Debug.Assert(elseValue != null, "CASE statement with no WHEN/THENs must have ELSE.");
                return(elseValue);
            }
        }
            internal static CqtExpression StripNull(LinqExpression sourceExpression,
                                                    DbExpression inputExpression, DbExpression outputExpression, bool useDatabaseNullSemantics)
            {
                if (sourceExpression.IsNullConstant())
                {
                    return(DbExpressionBuilder.Constant(string.Empty));
                }

                if (sourceExpression.NodeType == ExpressionType.Constant)
                {
                    return(outputExpression);
                }

                if (useDatabaseNullSemantics)
                {
                    return(outputExpression);
                }

                // converts evaluated null values to empty string, nullable primitive properties etc.
                var castNullToEmptyString = DbExpressionBuilder.Case(
                    new[] { inputExpression.IsNull() },
                    new[] { DbExpressionBuilder.Constant(string.Empty) },
                    outputExpression);

                return(castNullToEmptyString);
            }
Exemple #3
0
        private static DbExpression SimplifyCaseStatement(DbExpression expression)
        {
            var caseExpression = (DbCaseExpression)expression;

            // try simplifying predicates
            var predicateSimplified = false;
            var rewrittenPredicates = new List <DbExpression>(caseExpression.When.Count);

            foreach (var when in caseExpression.When)
            {
                DbExpression simplifiedPredicate;
                if (TrySimplifyPredicate(when, out simplifiedPredicate))
                {
                    rewrittenPredicates.Add(simplifiedPredicate);
                    predicateSimplified = true;
                }
                else
                {
                    rewrittenPredicates.Add(when);
                }
            }

            if (!predicateSimplified)
            {
                return(null);
            }

            caseExpression = DbExpressionBuilder.Case(rewrittenPredicates, caseExpression.Then, caseExpression.Else);
            return(caseExpression);
        }
Exemple #4
0
        private static DbExpression SimplifyCaseStatement(DbExpression expression)
        {
            DbCaseExpression    dbCaseExpression = (DbCaseExpression)expression;
            bool                flag             = false;
            List <DbExpression> dbExpressionList = new List <DbExpression>(dbCaseExpression.When.Count);

            foreach (DbExpression predicate in (IEnumerable <DbExpression>)dbCaseExpression.When)
            {
                DbExpression simplified;
                if (ViewSimplifier.TrySimplifyPredicate(predicate, out simplified))
                {
                    dbExpressionList.Add(simplified);
                    flag = true;
                }
                else
                {
                    dbExpressionList.Add(predicate);
                }
            }
            if (!flag)
            {
                return((DbExpression)null);
            }
            return((DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>)dbExpressionList, (IEnumerable <DbExpression>)dbCaseExpression.Then, dbCaseExpression.Else));
        }
 internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
 {
     if (m_expr.IsTrue || m_expr.IsFalse)
     {
         return(m_expr.AsCqt(row));
     }
     else
     {
         // Produce "CASE WHEN boolExpr THEN True ELSE False END" in order to enforce the two-state boolean logic:
         // if boolExpr returns the boolean Unknown, it gets converted to boolean False.
         return(DbExpressionBuilder.Case(new DbExpression[] { m_expr.AsCqt(row) }, new DbExpression[] { DbExpressionBuilder.True }, DbExpressionBuilder.False));
     }
 }
 internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
 {
     if (this.m_expr.IsTrue || this.m_expr.IsFalse)
     {
         return(this.m_expr.AsCqt(row));
     }
     return((DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>) new DbExpression[1]
     {
         this.m_expr.AsCqt(row)
     }, (IEnumerable <DbExpression>) new DbExpression[1]
     {
         (DbExpression)DbExpressionBuilder.True
     }, (DbExpression)DbExpressionBuilder.False));
 }
        internal DbExpression AsCqt(
            DbExpression row,
            IEnumerable <WithRelationship> withRelationships)
        {
            List <DbExpression> dbExpressionList1 = new List <DbExpression>();
            List <DbExpression> dbExpressionList2 = new List <DbExpression>();

            foreach (CaseStatement.WhenThen clause in this.Clauses)
            {
                dbExpressionList1.Add(clause.Condition.AsCqt(row));
                dbExpressionList2.Add(CaseStatement.CaseSlotValueAsCqt(row, clause.Value, this.MemberPath, withRelationships));
            }
            DbExpression elseExpression = this.ElseValue != null?CaseStatement.CaseSlotValueAsCqt(row, this.ElseValue, this.MemberPath, withRelationships) : Constant.Null.AsCqt(row, this.MemberPath);

            if (this.Clauses.Count > 0)
            {
                return((DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>)dbExpressionList1, (IEnumerable <DbExpression>)dbExpressionList2, elseExpression));
            }
            return(elseExpression);
        }
Exemple #8
0
        private DbExpression GenerateStructuralTypeResultMappingView(
            DbExpression storeFunctionInvoke,
            out DiscriminatorMap discriminatorMap)
        {
            discriminatorMap = (DiscriminatorMap)null;
            DbExpression dbExpression = storeFunctionInvoke;
            DbExpression queryView;

            if (this.m_structuralTypeMappings.Count == 1)
            {
                Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > structuralTypeMapping = this.m_structuralTypeMappings[0];
                StructuralType structuralType = structuralTypeMapping.Item1;
                List <ConditionPropertyMapping> conditions       = structuralTypeMapping.Item2;
                List <PropertyMapping>          propertyMappings = structuralTypeMapping.Item3;
                if (conditions.Count > 0)
                {
                    dbExpression = (DbExpression)dbExpression.Where((Func <DbExpression, DbExpression>)(row => FunctionImportMappingComposable.GenerateStructuralTypeConditionsPredicate(conditions, row)));
                }
                DbExpressionBinding input = dbExpression.BindAs("row");
                DbExpression        structuralTypeMappingView = FunctionImportMappingComposable.GenerateStructuralTypeMappingView(structuralType, propertyMappings, (DbExpression)input.Variable);
                queryView = (DbExpression)input.Project(structuralTypeMappingView);
            }
            else
            {
                DbExpressionBinding binding = dbExpression.BindAs("row");
                List <DbExpression> list    = this.m_structuralTypeMappings.Select <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >, DbExpression>((Func <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >, DbExpression>)(m => FunctionImportMappingComposable.GenerateStructuralTypeConditionsPredicate(m.Item2, (DbExpression)binding.Variable))).ToList <DbExpression>();
                binding = binding.Filter(Helpers.BuildBalancedTreeInPlace <DbExpression>((IList <DbExpression>)list.ToArray(), (Func <DbExpression, DbExpression, DbExpression>)((prev, next) => (DbExpression)prev.Or(next)))).BindAs("row");
                List <DbExpression> source = new List <DbExpression>(this.m_structuralTypeMappings.Count);
                foreach (Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > structuralTypeMapping in this.m_structuralTypeMappings)
                {
                    StructuralType         structuralType   = structuralTypeMapping.Item1;
                    List <PropertyMapping> propertyMappings = structuralTypeMapping.Item3;
                    source.Add(FunctionImportMappingComposable.GenerateStructuralTypeMappingView(structuralType, propertyMappings, (DbExpression)binding.Variable));
                }
                DbExpression projection = (DbExpression)DbExpressionBuilder.Case(list.Take <DbExpression>(this.m_structuralTypeMappings.Count - 1), source.Take <DbExpression>(this.m_structuralTypeMappings.Count - 1), source[this.m_structuralTypeMappings.Count - 1]);
                queryView = (DbExpression)binding.Project(projection);
                DiscriminatorMap.TryCreateDiscriminatorMap(this.FunctionImport.EntitySet, queryView, out discriminatorMap);
            }
            return(queryView);
        }
        public void Visit_DbCaseExpression_creates_equivalent_legacy_DbCaseExpression()
        {
            var whens =
                new[]
            {
                DbExpressionBuilder.Constant(42).NotEqual(DbExpressionBuilder.Constant(42)),
                DbExpressionBuilder.Constant(911).Equal(DbExpressionBuilder.Constant(911)),
            };

            var thens =
                new[]
            {
                DbExpressionBuilder.False,
                DbExpressionBuilder.True
            };

            var caseExpression =
                DbExpressionBuilder.Case(whens, thens, DbExpressionBuilder.False);

            var legacyCaseExpression =
                _legacyDbExpressionConverter.Visit(caseExpression) as LegacyCommandTrees.DbCaseExpression;

            Assert.NotNull(legacyCaseExpression);
            Assert.Equal(LegacyCommandTrees.DbExpressionKind.Case, legacyCaseExpression.ExpressionKind);
            Assert.Equal(2, legacyCaseExpression.When.Count);
            Assert.Equal(LegacyCommandTrees.DbExpressionKind.NotEquals, legacyCaseExpression.When[0].ExpressionKind);
            Assert.Equal(LegacyCommandTrees.DbExpressionKind.Equals, legacyCaseExpression.When[1].ExpressionKind);

            Assert.Equal(2, legacyCaseExpression.Then.Count);
            Assert.False((bool)((LegacyCommandTrees.DbConstantExpression)legacyCaseExpression.Then[0]).Value);
            Assert.True((bool)((LegacyCommandTrees.DbConstantExpression)legacyCaseExpression.Then[1]).Value);
            Assert.False((bool)((LegacyCommandTrees.DbConstantExpression)legacyCaseExpression.Else).Value);

            TypeUsageVerificationHelper
            .VerifyTypeUsagesEquivalent(legacyCaseExpression.ResultType, caseExpression.ResultType);
        }
Exemple #10
0
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression      lambdaExpression = expression as DbLambdaExpression;
            DbNewInstanceExpression newRow;

            if (lambdaExpression != null)
            {
                // NOTE: We rely on the fact that today span cannot be done over queries containing DbLambdaExpressions
                // created by users, because user-created expressions cannot be used for querying in O-space.
                // If that were to change, pushing span beyond a LambdaExpression could cause variable name
                // collisions between the variable names used in the Lambda and the names generated by the
                // RelationshipNavigationVisitor.
                newRow = lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            }
            else
            {
                newRow = expression as DbNewInstanceExpression;
            }

            Dictionary <int, DbExpression> unmodifiedColumns = null;
            Dictionary <int, DbExpression> spannedColumns    = null;

            for (int idx = 0; idx < rowType.Properties.Count; idx++)
            {
                // Retrieve the property that represents the current column
                EdmProperty columnProp = rowType.Properties[idx];

                // Construct an expression that defines the current column.
                DbExpression columnExpr = null;
                if (newRow != null)
                {
                    // For a row-constructing NewInstance expression, the corresponding argument can simply be used
                    columnExpr = newRow.Arguments[idx];
                }
                else
                {
                    // For all other expressions the property corresponding to the column name must be retrieved
                    // from the row-typed expression
                    columnExpr = expression.Property(columnProp.Name);
                }

                DbExpression spannedColumn = this.Rewrite(columnExpr);
                if (!object.ReferenceEquals(spannedColumn, columnExpr))
                {
                    // If so, then update the dictionary of column index to span information
                    if (null == spannedColumns)
                    {
                        spannedColumns = new Dictionary <int, DbExpression>();
                    }

                    spannedColumns[idx] = spannedColumn;
                }
                else
                {
                    // Otherwise, update the dictionary of column index to unmodified expression
                    if (null == unmodifiedColumns)
                    {
                        unmodifiedColumns = new Dictionary <int, DbExpression>();
                    }

                    unmodifiedColumns[idx] = columnExpr;
                }
            }

            // A new expression need only be built if at least one column was spanned
            if (null == spannedColumns)
            {
                // No columns were spanned, indicate that the original expression should remain.
                return(expression);
            }
            else
            {
                // At least one column was spanned, so build a new row constructor that defines the new row, including spanned columns.
                List <DbExpression> columnArguments = new List <DbExpression>(rowType.Properties.Count);
                List <EdmProperty>  properties      = new List <EdmProperty>(rowType.Properties.Count);
                for (int idx = 0; idx < rowType.Properties.Count; idx++)
                {
                    EdmProperty  columnProp = rowType.Properties[idx];
                    DbExpression columnDef  = null;
                    if (!spannedColumns.TryGetValue(idx, out columnDef))
                    {
                        columnDef = unmodifiedColumns[idx];
                    }
                    columnArguments.Add(columnDef);
                    properties.Add(new EdmProperty(columnProp.Name, columnDef.ResultType));
                }

                // Copy over any eLinq initializer metadata (if present, or null if not).
                // Note that this initializer metadata does not strictly match the new row type
                // that includes spanned columns, but will be correct once the object materializer
                // has interpreted the query results to produce the correct value for each colum.
                RowType      rewrittenRow          = new RowType(properties, rowType.InitializerMetadata);
                TypeUsage    rewrittenRowTypeUsage = TypeUsage.Create(rewrittenRow);
                DbExpression rewritten             = rewrittenRowTypeUsage.New(columnArguments);

                // SQLBUDT #554182: If we insert a new projection we should should make sure to
                // not interfere with the nullability of the input.
                // In particular, if the input row is null and we construct a new row as a projection over its columns
                // we would get a row consisting of nulls, instead of a null row.
                // Thus, given an input X, we rewritte it as:  if (X is null) then NULL else rewritten.
                if (newRow == null)
                {
                    DbExpression condition      = DbExpressionBuilder.CreateIsNullExpressionAllowingRowTypeArgument(expression);
                    DbExpression nullExpression = DbExpressionBuilder.Null(rewrittenRowTypeUsage);
                    rewritten = DbExpressionBuilder.Case(
                        new List <DbExpression>(new DbExpression[] { condition }),
                        new List <DbExpression>(new DbExpression[] { nullExpression }),
                        rewritten);
                }

                // Add an entry to the spanned row type => original row type map for the new row type.
                AddSpannedRowType(rewrittenRow, expression.ResultType);

                if (lambdaExpression != null && newRow != null)
                {
                    rewritten = DbLambda.Create(rewritten, lambdaExpression.Lambda.Variables).Invoke(lambdaExpression.Arguments);
                }

                return(rewritten);
            }
        }
        private DbExpression GenerateStructuralTypeResultMappingView(
            DbExpression storeFunctionInvoke, out DiscriminatorMap discriminatorMap)
        {
            Debug.Assert(
                m_structuralTypeMappings != null && m_structuralTypeMappings.Count > 0,
                "m_structuralTypeMappings != null && m_structuralTypeMappings.Count > 0");

            discriminatorMap = null;

            // Process explicit structural type mappings. The mapping is based on the direct call of the store function
            // wrapped into a projection constructing the mapped structural types.

            var queryExpression = storeFunctionInvoke;

            if (m_structuralTypeMappings.Count == 1)
            {
                var mapping = m_structuralTypeMappings[0];

                var type             = mapping.Item1;
                var conditions       = mapping.Item2;
                var propertyMappings = mapping.Item3;

                if (conditions.Count > 0)
                {
                    queryExpression = queryExpression.Where((row) => GenerateStructuralTypeConditionsPredicate(conditions, row));
                }

                var binding = queryExpression.BindAs("row");
                var entityTypeMappingView = GenerateStructuralTypeMappingView(type, propertyMappings, binding.Variable);

                queryExpression = binding.Project(entityTypeMappingView);
            }
            else
            {
                var binding = queryExpression.BindAs("row");

                // Make sure type projection is performed over a closed set where each row is guaranteed to produce a known type.
                // To do this, filter the store function output using the type conditions.
                Debug.Assert(m_structuralTypeMappings.All(m => m.Item2.Count > 0), "In multi-type mapping each type must have conditions.");
                var structuralTypePredicates =
                    m_structuralTypeMappings.Select(m => GenerateStructuralTypeConditionsPredicate(m.Item2, binding.Variable)).ToList();
                queryExpression = binding.Filter(
                    Helpers.BuildBalancedTreeInPlace(
                        structuralTypePredicates.ToArray(), // clone, otherwise BuildBalancedTreeInPlace will change it
                        (prev, next) => prev.Or(next)));
                binding = queryExpression.BindAs("row");

                var structuralTypeMappingViews = new List <DbExpression>(m_structuralTypeMappings.Count);
                foreach (var mapping in m_structuralTypeMappings)
                {
                    var type             = mapping.Item1;
                    var propertyMappings = mapping.Item3;

                    structuralTypeMappingViews.Add(GenerateStructuralTypeMappingView(type, propertyMappings, binding.Variable));
                }
                Debug.Assert(
                    structuralTypeMappingViews.Count == structuralTypePredicates.Count,
                    "structuralTypeMappingViews.Count == structuralTypePredicates.Count");

                // Because we are projecting over the closed set, we can convert the last WHEN THEN into ELSE.
                DbExpression typeConstructors = DbExpressionBuilder.Case(
                    structuralTypePredicates.Take(m_structuralTypeMappings.Count - 1),
                    structuralTypeMappingViews.Take(m_structuralTypeMappings.Count - 1),
                    structuralTypeMappingViews[m_structuralTypeMappings.Count - 1]);

                queryExpression = binding.Project(typeConstructors);

                if (DiscriminatorMap.TryCreateDiscriminatorMap(FunctionImport.EntitySet, queryExpression, out discriminatorMap))
                {
                    Debug.Assert(discriminatorMap != null, "discriminatorMap == null after it has been created");
                }
            }

            return(queryExpression);
        }
Exemple #12
0
        private DbExpression AddFkRelatedEntityRefs(DbExpression viewConstructor)
        {
            // If the extent being simplified is not a C-Space entity set, or if it has already
            // been processed by the simplifier, then keep the original expression by returning
            // null.
            //
            if (doNotProcess)
            {
                return(null);
            }

            if (extent.BuiltInTypeKind != BuiltInTypeKind.EntitySet
                ||
                extent.EntityContainer.DataSpace != DataSpace.CSpace)
            {
                doNotProcess = true;
                return(null);
            }

            // Get a reference to the entity set being simplified, and find all the foreign key
            // (foreign key) associations for which the association set references that entity set,
            // with either association end.
            //
            var targetSet = (EntitySet)extent;
            var relSets   =
                targetSet.EntityContainer.BaseEntitySets
                .Where(es => es.BuiltInTypeKind == BuiltInTypeKind.AssociationSet)
                .Cast <AssociationSet>()
                .Where(
                    assocSet =>
                    assocSet.ElementType.IsForeignKey &&
                    assocSet.AssociationSetEnds.Any(se => se.EntitySet == targetSet)
                    )
                .ToList();

            // If no foreign key association sets that reference the entity set are present, then
            // no further processing is necessary, because FK-based related entity references cannot
            // be computed and added to the entities constructed for the entity set.
            if (relSets.Count == 0)
            {
                doNotProcess = true;
                return(null);
            }

            // For every relationship set that references this entity set, the relationship type and
            // foreign key constraint are used to determine if the entity set is the dependent set.
            // If it is the dependent set, then it is possible to augment the view definition with a
            // related entity ref that represents the navigation of the relationship set's relationship
            // from the dependent end (this entity set) to the the principal end (the entity set that
            // is referenced by the other association set end of the relationship set).
            //
            var principalSetsAndDependentTypes = new HashSet <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint> >();

            foreach (var relSet in relSets)
            {
                // Retrieve the single referential constraint from the foreign key association, and
                // use it to determine whether the association set end that represents the dependent
                // end of the association references this entity set.
                //
                var fkConstraint    = relSet.ElementType.ReferentialConstraints[0];
                var dependentSetEnd = relSet.AssociationSetEnds[fkConstraint.ToRole.Name];

                if (dependentSetEnd.EntitySet == targetSet)
                {
                    var requiredSourceNavType =
                        (EntityType)TypeHelpers.GetEdmType <RefType>(dependentSetEnd.CorrespondingAssociationEndMember.TypeUsage).ElementType;
                    var principalSetEnd = relSet.AssociationSetEnds[fkConstraint.FromRole.Name];

                    // Record the entity type that an element of this dependent entity set must have in order
                    // to be a valid navigation source for the relationship set's relationship, along with the
                    // association set end for the destination (principal) end of the navigation and the FK
                    // constraint that is associated with the relationship type. This information may be used
                    // later to construct a related entity ref for any entity constructor expression in the view
                    // that produces an entity of the required source type or a subtype.
                    //
                    principalSetsAndDependentTypes.Add(Tuple.Create(requiredSourceNavType, principalSetEnd, fkConstraint));
                }
            }

            // If no foreign key association sets that use the entity set as the dependent set are present,
            // then no further processing is possible, since FK-based related entity refs can only be added
            // to the view definition for navigations from the dependent end of the relationship to the principal.
            //
            if (principalSetsAndDependentTypes.Count == 0)
            {
                doNotProcess = true;
                return(null);
            }

            // This rule supports a view that is capped with a projection of the form
            // (input).Project(x => new Entity())
            // or
            // (input).Project(x => CASE WHEN (condition1) THEN new Entity1() ELSE WHEN (condition2) THEN new Entity2()... ELSE new EntityN())
            // where every new instance expression Entity1()...EntityN() constructs an entity of a type
            // that is compatible with the entity set's element type.
            // Here, the list of all DbNewInstanceExpressions contained in the projection is remembered,
            // along with any CASE statement conditions, if present. These expressions will be updated
            // if necessary and used to build a new capping projection if any of the entity constructors
            // are augmented with FK-based related entity references.
            //
            var entityProject = (DbProjectExpression)viewConstructor;
            var constructors  = new List <DbNewInstanceExpression>();
            List <DbExpression> conditions = null;

            if (entityProject.Projection.ExpressionKind
                == DbExpressionKind.Case)
            {
                // If the projection is a DbCaseExpression, then every result must be a DbNewInstanceExpression
                var discriminatedConstructor = (DbCaseExpression)entityProject.Projection;
                conditions = new List <DbExpression>(discriminatedConstructor.When.Count);
                for (var idx = 0; idx < discriminatedConstructor.When.Count; idx++)
                {
                    conditions.Add(discriminatedConstructor.When[idx]);
                    constructors.Add((DbNewInstanceExpression)discriminatedConstructor.Then[idx]);
                }
                constructors.Add((DbNewInstanceExpression)discriminatedConstructor.Else);
            }
            else
            {
                // Otherwise, the projection must be a single DbNewInstanceExpression
                constructors.Add((DbNewInstanceExpression)entityProject.Projection);
            }

            var rebuildView = false;

            for (var idx = 0; idx < constructors.Count; idx++)
            {
                var entityConstructor     = constructors[idx];
                var constructedEntityType = TypeHelpers.GetEdmType <EntityType>(entityConstructor.ResultType);

                var relatedRefs =
                    principalSetsAndDependentTypes
                    .Where(psdt => constructedEntityType == psdt.Item1 || constructedEntityType.IsSubtypeOf(psdt.Item1))
                    .Select(
                        psdt => RelatedEntityRefFromAssociationSetEnd(constructedEntityType, entityConstructor, psdt.Item2, psdt.Item3))
                    .ToList();

                if (relatedRefs.Count > 0)
                {
                    if (entityConstructor.HasRelatedEntityReferences)
                    {
                        relatedRefs = entityConstructor.RelatedEntityReferences.Concat(relatedRefs).ToList();
                    }

                    entityConstructor = DbExpressionBuilder.CreateNewEntityWithRelationshipsExpression(
                        constructedEntityType, entityConstructor.Arguments, relatedRefs);
                    constructors[idx] = entityConstructor;
                    rebuildView       = true;
                }
            }

            // Default to returning null to indicate that this rule did not produce a modified expression
            //
            DbExpression result = null;

            if (rebuildView)
            {
                // rebuildView is true, so entity constructing DbNewInstanceExpression(s) were encountered
                // and updated with additional related entity refs. The DbProjectExpression that caps the
                // view definition therefore needs to be rebuilt and returned as the result of this rule.
                //
                if (conditions != null)
                {
                    // The original view definition projection was a DbCaseExpression.
                    // The new expression is also a DbCaseExpression that uses the conditions from the
                    // original expression together with the updated result expressions to produce the
                    // new capping projection.
                    //
                    var whens = new List <DbExpression>(conditions.Count);
                    var thens = new List <DbExpression>(conditions.Count);
                    for (var idx = 0; idx < conditions.Count; idx++)
                    {
                        whens.Add(conditions[idx]);
                        thens.Add(constructors[idx]);
                    }

                    result = entityProject.Input.Project(DbExpressionBuilder.Case(whens, thens, constructors[conditions.Count]));
                }
                else
                {
                    // Otherwise, the capping projection consists entirely of the updated DbNewInstanceExpression.
                    //
                    result = entityProject.Input.Project(constructors[0]);
                }
            }

            // Regardless of whether or not the view was updated, this rule should not be applied again during rule processing
            doNotProcess = true;
            return(result);
        }
Exemple #13
0
        private static DbExpression SimplifyNestedTphDiscriminator(DbExpression expression)
        {
            var entityProjection    = (DbProjectExpression)expression;
            var booleanColumnFilter = (DbFilterExpression)entityProjection.Input.Expression;
            var rowProjection       = (DbProjectExpression)booleanColumnFilter.Input.Expression;
            var discriminatorFilter = (DbFilterExpression)rowProjection.Input.Expression;

            var predicates         = FlattenOr(booleanColumnFilter.Predicate).ToList();
            var propertyPredicates =
                predicates.OfType <DbPropertyExpression>()
                .Where(
                    px => px.Instance.ExpressionKind == DbExpressionKind.VariableReference &&
                    ((DbVariableReferenceExpression)px.Instance).VariableName == booleanColumnFilter.Input.VariableName)
                .ToList();

            if (predicates.Count
                != propertyPredicates.Count)
            {
                return(null);
            }

            var predicateColumnNames = propertyPredicates.Select(px => px.Property.Name).ToList();

            var discriminatorPredicates = new Dictionary <object, DbComparisonExpression>();

            if (!TypeSemantics.IsEntityType(discriminatorFilter.Input.VariableType)
                ||
                !TryMatchDiscriminatorPredicate(discriminatorFilter, (compEx, discValue) => discriminatorPredicates.Add(discValue, compEx)))
            {
                return(null);
            }

            var discriminatorProp    = (EdmProperty)((DbPropertyExpression)(discriminatorPredicates.First().Value).Left).Property;
            var rowConstructor       = (DbNewInstanceExpression)rowProjection.Projection;
            var resultRow            = TypeHelpers.GetEdmType <RowType>(rowConstructor.ResultType);
            var inputPredicateMap    = new Dictionary <string, DbComparisonExpression>();
            var selectorPredicateMap = new Dictionary <string, DbComparisonExpression>();
            var columnValues         = new Dictionary <string, DbExpression>(rowConstructor.Arguments.Count);

            for (var idx = 0; idx < rowConstructor.Arguments.Count; idx++)
            {
                var propName  = resultRow.Properties[idx].Name;
                var columnVal = rowConstructor.Arguments[idx];
                if (predicateColumnNames.Contains(propName))
                {
                    if (columnVal.ExpressionKind
                        != DbExpressionKind.Case)
                    {
                        return(null);
                    }
                    var casePredicate = (DbCaseExpression)columnVal;
                    if (casePredicate.When.Count != 1
                        ||
                        !TypeSemantics.IsBooleanType(casePredicate.Then[0].ResultType) ||
                        !TypeSemantics.IsBooleanType(casePredicate.Else.ResultType)
                        ||
                        casePredicate.Then[0].ExpressionKind != DbExpressionKind.Constant ||
                        casePredicate.Else.ExpressionKind != DbExpressionKind.Constant
                        ||
                        (bool)((DbConstantExpression)casePredicate.Then[0]).Value != true ||
                        (bool)((DbConstantExpression)casePredicate.Else).Value)
                    {
                        return(null);
                    }

                    DbPropertyExpression comparedProp;
                    object constValue;
                    if (
                        !TryMatchPropertyEqualsValue(
                            casePredicate.When[0], rowProjection.Input.VariableName, out comparedProp, out constValue)
                        ||
                        comparedProp.Property != discriminatorProp
                        ||
                        !discriminatorPredicates.ContainsKey(constValue))
                    {
                        return(null);
                    }

                    inputPredicateMap.Add(propName, discriminatorPredicates[constValue]);
                    selectorPredicateMap.Add(propName, (DbComparisonExpression)casePredicate.When[0]);
                }
                else
                {
                    columnValues.Add(propName, columnVal);
                }
            }

            // Build a new discriminator-based filter that only includes the same rows allowed by the higher '_from0' column-based filter
            var newDiscriminatorPredicate = Helpers.BuildBalancedTreeInPlace(
                new List <DbExpression>(inputPredicateMap.Values), (left, right) => left.Or(right));

            discriminatorFilter = discriminatorFilter.Input.Filter(newDiscriminatorPredicate);

            var entitySelector = (DbCaseExpression)entityProjection.Projection;
            var newWhens       = new List <DbExpression>(entitySelector.When.Count);
            var newThens       = new List <DbExpression>(entitySelector.Then.Count);

            for (var idx = 0; idx < entitySelector.When.Count; idx++)
            {
                var propWhen   = (DbPropertyExpression)entitySelector.When[idx];
                var entityThen = (DbNewInstanceExpression)entitySelector.Then[idx];

                DbComparisonExpression discriminatorWhen;
                if (!selectorPredicateMap.TryGetValue(propWhen.Property.Name, out discriminatorWhen))
                {
                    return(null);
                }
                newWhens.Add(discriminatorWhen);

                var inputBoundEntityConstructor = ValueSubstituter.Substitute(entityThen, entityProjection.Input.VariableName, columnValues);
                newThens.Add(inputBoundEntityConstructor);
            }

            var newElse           = ValueSubstituter.Substitute(entitySelector.Else, entityProjection.Input.VariableName, columnValues);
            var newEntitySelector = DbExpressionBuilder.Case(newWhens, newThens, newElse);

            DbExpression result = discriminatorFilter.BindAs(rowProjection.Input.VariableName).Project(newEntitySelector);

            return(result);
        }
Exemple #14
0
        protected override Expression VisitBinary(BinaryExpression node)
        {
#if (DEBUG_VISITS)
            System.Diagnostics.Debug.Print("VisitBinary: {0}", node);
#endif

            var expression = base.VisitBinary(node) as BinaryExpression;

            DbExpression dbExpression;

            //  Need special handling for comparisons against the null constant.  If we don't translate these
            //  using an "IsNull" expression, EF will convert it literally as "= null" which doesn't work in SQL Server.
            if (IsNullConstantExpression(expression.Right))
            {
                dbExpression = MapNullComparison(expression.Left, expression.NodeType);
            }
            else if (IsNullConstantExpression(expression.Left))
            {
                dbExpression = MapNullComparison(expression.Right, expression.NodeType);
            }
            else
            {
                DbExpression leftExpression  = GetDbExpressionForExpression(expression.Left);
                DbExpression rightExpression = GetDbExpressionForExpression(expression.Right);

                switch (expression.NodeType)
                {
                case ExpressionType.Equal:
                    //  DbPropertyExpression = class property that has been mapped to a database column
                    //  DbParameterReferenceExpression = lambda parameter
                    if (IsNullableExpressionOfType <DbPropertyExpression>(leftExpression) && IsNullableExpressionOfType <DbParameterReferenceExpression>(rightExpression))
                    {
                        dbExpression = CreateEqualComparisonOfNullablePropToNullableParam(leftExpression, rightExpression);
                    }
                    else if (IsNullableExpressionOfType <DbPropertyExpression>(rightExpression) && IsNullableExpressionOfType <DbParameterReferenceExpression>(leftExpression))
                    {
                        dbExpression = CreateEqualComparisonOfNullablePropToNullableParam(rightExpression, leftExpression);
                    }
                    else
                    {
                        dbExpression = DbExpressionBuilder.Equal(leftExpression, rightExpression);
                    }
                    break;

                case ExpressionType.NotEqual:
                    dbExpression = DbExpressionBuilder.NotEqual(leftExpression, rightExpression);
                    break;

                case ExpressionType.GreaterThan:
                    dbExpression = DbExpressionBuilder.GreaterThan(leftExpression, rightExpression);
                    break;

                case ExpressionType.GreaterThanOrEqual:
                    dbExpression = DbExpressionBuilder.GreaterThanOrEqual(leftExpression, rightExpression);
                    break;

                case ExpressionType.LessThan:
                    dbExpression = DbExpressionBuilder.LessThan(leftExpression, rightExpression);
                    break;

                case ExpressionType.LessThanOrEqual:
                    dbExpression = DbExpressionBuilder.LessThanOrEqual(leftExpression, rightExpression);
                    break;

                case ExpressionType.AndAlso:
                    dbExpression = DbExpressionBuilder.And(leftExpression, rightExpression);
                    break;

                case ExpressionType.OrElse:
                    dbExpression = DbExpressionBuilder.Or(leftExpression, rightExpression);
                    break;

                case ExpressionType.And:
                    dbExpression = EdmFunctions.BitwiseAnd(leftExpression, rightExpression);
                    break;

                case ExpressionType.Or:
                    dbExpression = EdmFunctions.BitwiseOr(leftExpression, rightExpression);
                    break;

                case ExpressionType.ExclusiveOr:
                    dbExpression = EdmFunctions.BitwiseXor(leftExpression, rightExpression);
                    break;

                case ExpressionType.Coalesce:
                    //  EF does not expose the "coalesce" function.  So best we can do is a case statement.  Issue #77.
                    var whenExpressions = new List <DbExpression>()
                    {
                        DbExpressionBuilder.IsNull(leftExpression)
                    };
                    var thenExpressions = new List <DbExpression>()
                    {
                        rightExpression
                    };
                    dbExpression = DbExpressionBuilder.Case(whenExpressions, thenExpressions, leftExpression);
                    break;

                default:
                    throw new NotImplementedException(string.Format("Unhandled NodeType of {0} in LambdaToDbExpressionVisitor.VisitBinary", expression.NodeType));
                }
            }

            MapExpressionToDbExpression(expression, dbExpression);

            return(expression);
        }
        private DbExpression RewriteRow(DbExpression expression, RowType rowType)
        {
            DbLambdaExpression             lambdaExpression   = expression as DbLambdaExpression;
            DbNewInstanceExpression        instanceExpression = lambdaExpression == null ? expression as DbNewInstanceExpression : lambdaExpression.Lambda.Body as DbNewInstanceExpression;
            Dictionary <int, DbExpression> dictionary1        = (Dictionary <int, DbExpression>)null;
            Dictionary <int, DbExpression> dictionary2        = (Dictionary <int, DbExpression>)null;

            for (int index = 0; index < rowType.Properties.Count; ++index)
            {
                EdmProperty  property     = rowType.Properties[index];
                DbExpression expression1  = instanceExpression == null ? (DbExpression)expression.Property(property.Name) : instanceExpression.Arguments[index];
                DbExpression dbExpression = this.Rewrite(expression1);
                if (!object.ReferenceEquals((object)dbExpression, (object)expression1))
                {
                    if (dictionary2 == null)
                    {
                        dictionary2 = new Dictionary <int, DbExpression>();
                    }
                    dictionary2[index] = dbExpression;
                }
                else
                {
                    if (dictionary1 == null)
                    {
                        dictionary1 = new Dictionary <int, DbExpression>();
                    }
                    dictionary1[index] = expression1;
                }
            }
            if (dictionary2 == null)
            {
                return(expression);
            }
            List <DbExpression> dbExpressionList = new List <DbExpression>(rowType.Properties.Count);
            List <EdmProperty>  edmPropertyList  = new List <EdmProperty>(rowType.Properties.Count);

            for (int key = 0; key < rowType.Properties.Count; ++key)
            {
                EdmProperty  property     = rowType.Properties[key];
                DbExpression dbExpression = (DbExpression)null;
                if (!dictionary2.TryGetValue(key, out dbExpression))
                {
                    dbExpression = dictionary1[key];
                }
                dbExpressionList.Add(dbExpression);
                edmPropertyList.Add(new EdmProperty(property.Name, dbExpression.ResultType));
            }
            RowType      spannedType   = new RowType((IEnumerable <EdmProperty>)edmPropertyList, rowType.InitializerMetadata);
            TypeUsage    typeUsage     = TypeUsage.Create((EdmType)spannedType);
            DbExpression dbExpression1 = (DbExpression)typeUsage.New((IEnumerable <DbExpression>)dbExpressionList);

            if (instanceExpression == null)
            {
                dbExpression1 = (DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>) new DbExpression[1]
                {
                    (DbExpression)expression.IsNull()
                }), (IEnumerable <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>) new DbExpression[1]
                {
                    (DbExpression)typeUsage.Null()
                }), dbExpression1);
            }
            this.AddSpannedRowType(spannedType, expression.ResultType);
            if (lambdaExpression != null && instanceExpression != null)
            {
                dbExpression1 = (DbExpression)DbLambda.Create(dbExpression1, (IEnumerable <DbVariableReferenceExpression>)lambdaExpression.Lambda.Variables).Invoke((IEnumerable <DbExpression>)lambdaExpression.Arguments);
            }
            return(dbExpression1);
        }
Exemple #16
0
        private DbExpression AddFkRelatedEntityRefs(DbExpression viewConstructor)
        {
            if (this.doNotProcess)
            {
                return((DbExpression)null);
            }
            if (this.extent.BuiltInTypeKind != BuiltInTypeKind.EntitySet || this.extent.EntityContainer.DataSpace != DataSpace.CSpace)
            {
                this.doNotProcess = true;
                return((DbExpression)null);
            }
            EntitySet             targetSet = (EntitySet)this.extent;
            List <AssociationSet> list1     = targetSet.EntityContainer.BaseEntitySets.Where <EntitySetBase>((Func <EntitySetBase, bool>)(es => es.BuiltInTypeKind == BuiltInTypeKind.AssociationSet)).Cast <AssociationSet>().Where <AssociationSet>((Func <AssociationSet, bool>)(assocSet =>
            {
                if (assocSet.ElementType.IsForeignKey)
                {
                    return(assocSet.AssociationSetEnds.Any <AssociationSetEnd>((Func <AssociationSetEnd, bool>)(se => se.EntitySet == targetSet)));
                }
                return(false);
            })).ToList <AssociationSet>();

            if (list1.Count == 0)
            {
                this.doNotProcess = true;
                return((DbExpression)null);
            }
            HashSet <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint> > source = new HashSet <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint> >();

            foreach (AssociationSet associationSet in list1)
            {
                ReferentialConstraint referentialConstraint = associationSet.ElementType.ReferentialConstraints[0];
                AssociationSetEnd     associationSetEnd1    = associationSet.AssociationSetEnds[referentialConstraint.ToRole.Name];
                if (associationSetEnd1.EntitySet == targetSet)
                {
                    EntityType        elementType        = (EntityType)TypeHelpers.GetEdmType <RefType>(associationSetEnd1.CorrespondingAssociationEndMember.TypeUsage).ElementType;
                    AssociationSetEnd associationSetEnd2 = associationSet.AssociationSetEnds[referentialConstraint.FromRole.Name];
                    source.Add(Tuple.Create <EntityType, AssociationSetEnd, ReferentialConstraint>(elementType, associationSetEnd2, referentialConstraint));
                }
            }
            if (source.Count == 0)
            {
                this.doNotProcess = true;
                return((DbExpression)null);
            }
            DbProjectExpression            projectExpression      = (DbProjectExpression)viewConstructor;
            List <DbNewInstanceExpression> instanceExpressionList = new List <DbNewInstanceExpression>();
            List <DbExpression>            dbExpressionList1      = (List <DbExpression>)null;

            if (projectExpression.Projection.ExpressionKind == DbExpressionKind.Case)
            {
                DbCaseExpression projection = (DbCaseExpression)projectExpression.Projection;
                dbExpressionList1 = new List <DbExpression>(projection.When.Count);
                for (int index = 0; index < projection.When.Count; ++index)
                {
                    dbExpressionList1.Add(projection.When[index]);
                    instanceExpressionList.Add((DbNewInstanceExpression)projection.Then[index]);
                }
                instanceExpressionList.Add((DbNewInstanceExpression)projection.Else);
            }
            else
            {
                instanceExpressionList.Add((DbNewInstanceExpression)projectExpression.Projection);
            }
            bool flag = false;

            for (int index = 0; index < instanceExpressionList.Count; ++index)
            {
                DbNewInstanceExpression entityConstructor = instanceExpressionList[index];
                EntityType constructedEntityType          = TypeHelpers.GetEdmType <EntityType>(entityConstructor.ResultType);
                List <DbRelatedEntityRef> list2           = source.Where <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint> >((Func <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint>, bool>)(psdt =>
                {
                    if (constructedEntityType != psdt.Item1)
                    {
                        return(constructedEntityType.IsSubtypeOf((EdmType)psdt.Item1));
                    }
                    return(true);
                })).Select <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint>, DbRelatedEntityRef>((Func <Tuple <EntityType, AssociationSetEnd, ReferentialConstraint>, DbRelatedEntityRef>)(psdt => ViewSimplifier.RelatedEntityRefFromAssociationSetEnd(constructedEntityType, entityConstructor, psdt.Item2, psdt.Item3))).ToList <DbRelatedEntityRef>();
                if (list2.Count > 0)
                {
                    if (entityConstructor.HasRelatedEntityReferences)
                    {
                        list2 = entityConstructor.RelatedEntityReferences.Concat <DbRelatedEntityRef>((IEnumerable <DbRelatedEntityRef>)list2).ToList <DbRelatedEntityRef>();
                    }
                    entityConstructor             = DbExpressionBuilder.CreateNewEntityWithRelationshipsExpression(constructedEntityType, entityConstructor.Arguments, (IList <DbRelatedEntityRef>)list2);
                    instanceExpressionList[index] = entityConstructor;
                    flag = true;
                }
            }
            DbExpression dbExpression = (DbExpression)null;

            if (flag)
            {
                if (dbExpressionList1 != null)
                {
                    List <DbExpression> dbExpressionList2 = new List <DbExpression>(dbExpressionList1.Count);
                    List <DbExpression> dbExpressionList3 = new List <DbExpression>(dbExpressionList1.Count);
                    for (int index = 0; index < dbExpressionList1.Count; ++index)
                    {
                        dbExpressionList2.Add(dbExpressionList1[index]);
                        dbExpressionList3.Add((DbExpression)instanceExpressionList[index]);
                    }
                    dbExpression = (DbExpression)projectExpression.Input.Project((DbExpression)DbExpressionBuilder.Case((IEnumerable <DbExpression>)dbExpressionList2, (IEnumerable <DbExpression>)dbExpressionList3, (DbExpression)instanceExpressionList[dbExpressionList1.Count]));
                }
                else
                {
                    dbExpression = (DbExpression)projectExpression.Input.Project((DbExpression)instanceExpressionList[0]);
                }
            }
            this.doNotProcess = true;
            return(dbExpression);
        }
Exemple #17
0
        private static DbExpression SimplifyNestedTphDiscriminator(DbExpression expression)
        {
            DbProjectExpression         projectExpression   = (DbProjectExpression)expression;
            DbFilterExpression          booleanColumnFilter = (DbFilterExpression)projectExpression.Input.Expression;
            DbProjectExpression         expression1         = (DbProjectExpression)booleanColumnFilter.Input.Expression;
            DbFilterExpression          expression2         = (DbFilterExpression)expression1.Input.Expression;
            List <DbExpression>         list1 = ViewSimplifier.FlattenOr(booleanColumnFilter.Predicate).ToList <DbExpression>();
            List <DbPropertyExpression> list2 = list1.OfType <DbPropertyExpression>().Where <DbPropertyExpression>((Func <DbPropertyExpression, bool>)(px =>
            {
                if (px.Instance.ExpressionKind == DbExpressionKind.VariableReference)
                {
                    return(((DbVariableReferenceExpression)px.Instance).VariableName == booleanColumnFilter.Input.VariableName);
                }
                return(false);
            })).ToList <DbPropertyExpression>();

            if (list1.Count != list2.Count)
            {
                return((DbExpression)null);
            }
            List <string> list3 = list2.Select <DbPropertyExpression, string>((Func <DbPropertyExpression, string>)(px => px.Property.Name)).ToList <string>();
            Dictionary <object, DbComparisonExpression> discriminatorPredicates = new Dictionary <object, DbComparisonExpression>();

            if (!TypeSemantics.IsEntityType(expression2.Input.VariableType) || !ViewSimplifier.TryMatchDiscriminatorPredicate(expression2, (Action <DbComparisonExpression, object>)((compEx, discValue) => discriminatorPredicates.Add(discValue, compEx))))
            {
                return((DbExpression)null);
            }
            EdmProperty             property1   = (EdmProperty)((DbPropertyExpression)discriminatorPredicates.First <KeyValuePair <object, DbComparisonExpression> >().Value.Left).Property;
            DbNewInstanceExpression projection1 = (DbNewInstanceExpression)expression1.Projection;
            RowType edmType = TypeHelpers.GetEdmType <RowType>(projection1.ResultType);
            Dictionary <string, DbComparisonExpression> dictionary1    = new Dictionary <string, DbComparisonExpression>();
            Dictionary <string, DbComparisonExpression> dictionary2    = new Dictionary <string, DbComparisonExpression>();
            Dictionary <string, DbExpression>           propertyValues = new Dictionary <string, DbExpression>(projection1.Arguments.Count);

            for (int index = 0; index < projection1.Arguments.Count; ++index)
            {
                string       name         = edmType.Properties[index].Name;
                DbExpression dbExpression = projection1.Arguments[index];
                if (list3.Contains(name))
                {
                    if (dbExpression.ExpressionKind != DbExpressionKind.Case)
                    {
                        return((DbExpression)null);
                    }
                    DbCaseExpression dbCaseExpression = (DbCaseExpression)dbExpression;
                    if (dbCaseExpression.When.Count != 1 || !TypeSemantics.IsBooleanType(dbCaseExpression.Then[0].ResultType) || (!TypeSemantics.IsBooleanType(dbCaseExpression.Else.ResultType) || dbCaseExpression.Then[0].ExpressionKind != DbExpressionKind.Constant) || (dbCaseExpression.Else.ExpressionKind != DbExpressionKind.Constant || !(bool)((DbConstantExpression)dbCaseExpression.Then[0]).Value || (bool)((DbConstantExpression)dbCaseExpression.Else).Value))
                    {
                        return((DbExpression)null);
                    }
                    DbPropertyExpression property2;
                    object key;
                    if (!ViewSimplifier.TryMatchPropertyEqualsValue(dbCaseExpression.When[0], expression1.Input.VariableName, out property2, out key) || property2.Property != property1 || !discriminatorPredicates.ContainsKey(key))
                    {
                        return((DbExpression)null);
                    }
                    dictionary1.Add(name, discriminatorPredicates[key]);
                    dictionary2.Add(name, (DbComparisonExpression)dbCaseExpression.When[0]);
                }
                else
                {
                    propertyValues.Add(name, dbExpression);
                }
            }
            DbExpression        predicate         = Helpers.BuildBalancedTreeInPlace <DbExpression>((IList <DbExpression>) new List <DbExpression>((IEnumerable <DbExpression>)dictionary1.Values), (Func <DbExpression, DbExpression, DbExpression>)((left, right) => (DbExpression)left.Or(right)));
            DbFilterExpression  input             = expression2.Input.Filter(predicate);
            DbCaseExpression    projection2       = (DbCaseExpression)projectExpression.Projection;
            List <DbExpression> dbExpressionList1 = new List <DbExpression>(projection2.When.Count);
            List <DbExpression> dbExpressionList2 = new List <DbExpression>(projection2.Then.Count);

            for (int index = 0; index < projection2.When.Count; ++index)
            {
                DbPropertyExpression    propertyExpression = (DbPropertyExpression)projection2.When[index];
                DbNewInstanceExpression instanceExpression = (DbNewInstanceExpression)projection2.Then[index];
                DbComparisonExpression  comparisonExpression;
                if (!dictionary2.TryGetValue(propertyExpression.Property.Name, out comparisonExpression))
                {
                    return((DbExpression)null);
                }
                dbExpressionList1.Add((DbExpression)comparisonExpression);
                DbExpression dbExpression = ViewSimplifier.ValueSubstituter.Substitute((DbExpression)instanceExpression, projectExpression.Input.VariableName, propertyValues);
                dbExpressionList2.Add(dbExpression);
            }
            DbExpression     elseExpression    = ViewSimplifier.ValueSubstituter.Substitute(projection2.Else, projectExpression.Input.VariableName, propertyValues);
            DbCaseExpression dbCaseExpression1 = DbExpressionBuilder.Case((IEnumerable <DbExpression>)dbExpressionList1, (IEnumerable <DbExpression>)dbExpressionList2, elseExpression);

            return((DbExpression)input.BindAs(expression1.Input.VariableName).Project((DbExpression)dbCaseExpression1));
        }
            internal static DbExpression ConvertToString(ExpressionConverter parent, LinqExpression linqExpression)
            {
                if (linqExpression.Type == typeof(object))
                {
                    var constantExpression = linqExpression as ConstantExpression;
                    linqExpression =
                        constantExpression != null?
                        Expression.Constant(constantExpression.Value) :
                            linqExpression.RemoveConvert();
                }

                var expression = parent.TranslateExpression(linqExpression);
                var clrType    = TypeSystem.GetNonNullableType(linqExpression.Type);

                if (clrType.IsEnum)
                {
                    //Flag enums are not supported.
                    if (Attribute.IsDefined(clrType, typeof(FlagsAttribute)))
                    {
                        throw new NotSupportedException(Strings.Elinq_ToStringNotSupportedForEnumsWithFlags);
                    }

                    if (linqExpression.IsNullConstant())
                    {
                        return(DbExpressionBuilder.Constant(string.Empty));
                    }

                    //Constant expression, optimize to constant name
                    if (linqExpression.NodeType == ExpressionType.Constant)
                    {
                        var value = ((ConstantExpression)linqExpression).Value;
                        var name  = Enum.GetName(clrType, value) ?? value.ToString();
                        return(DbExpressionBuilder.Constant(name));
                    }

                    var integralType = clrType.GetEnumUnderlyingType();
                    var type         = parent.GetValueLayerType(integralType);

                    var values = clrType.GetEnumValues()
                                 .Cast <object>()
                                 .Select(v => System.Convert.ChangeType(v, integralType, CultureInfo.InvariantCulture)) //cast to integral type so that unmapped enum types works too
                                 .Select(v => DbExpressionBuilder.Constant(v))
                                 .Select(c => (DbExpression)expression.CastTo(type).Equal(c))                           //cast expression to integral type before comparing to constant
                                 .Concat(new[] { expression.CastTo(type).IsNull() });                                   // default case

                    var names = clrType.GetEnumNames()
                                .Select(s => DbExpressionBuilder.Constant(s))
                                .Concat(new[] { DbExpressionBuilder.Constant(string.Empty) }); // default case

                    //translate unnamed enum values for the else clause, raw linq -> as integral value -> translate to cqt -> to string
                    //e.g.  ((DayOfWeek)99) -> "99"
                    var asIntegralLinq = LinqExpression.Convert(linqExpression, integralType);
                    var asStringCqt    = parent
                                         .TranslateExpression(asIntegralLinq)
                                         .CastTo(parent.GetValueLayerType(typeof(string)));

                    return(DbExpressionBuilder.Case(values, names, asStringCqt));
                }
                else if (TypeSemantics.IsPrimitiveType(expression.ResultType, PrimitiveTypeKind.String))
                {
                    return(StripNull(linqExpression, expression, expression));
                }
                else if (TypeSemantics.IsPrimitiveType(expression.ResultType, PrimitiveTypeKind.Guid))
                {
                    return(StripNull(linqExpression, expression, expression.CastTo(parent.GetValueLayerType(typeof(string))).ToLower()));
                }
                else if (TypeSemantics.IsPrimitiveType(expression.ResultType, PrimitiveTypeKind.Boolean))
                {
                    if (linqExpression.IsNullConstant())
                    {
                        return(DbExpressionBuilder.Constant(string.Empty));
                    }

                    if (linqExpression.NodeType == ExpressionType.Constant)
                    {
                        var name = ((ConstantExpression)linqExpression).Value.ToString();
                        return(DbExpressionBuilder.Constant(name));
                    }

                    var whenTrue  = expression.Equal(DbExpressionBuilder.True);
                    var whenFalse = expression.Equal(DbExpressionBuilder.False);
                    var thenTrue  = DbExpressionBuilder.Constant(true.ToString());
                    var thenFalse = DbExpressionBuilder.Constant(false.ToString());

                    return(DbExpressionBuilder.Case(
                               new[] { whenTrue, whenFalse },
                               new[] { thenTrue, thenFalse },
                               DbExpressionBuilder.Constant(string.Empty)));
                }
                else
                {
                    if (!SupportsCastToString(expression.ResultType))
                    {
                        throw new NotSupportedException(
                                  Strings.Elinq_ToStringNotSupportedForType(expression.ResultType.EdmType.Name));
                    }

                    //treat all other types as a simple cast
                    return(StripNull(linqExpression, expression, expression.CastTo(parent.GetValueLayerType(typeof(string)))));
                }
            }