public override Expression Visit(DbCaseExpression expression)
        {
            List<Expression> cases = new List<Expression>() { this.Visit(expression.Else) };

            for (int i = expression.When.Count - 1; i >= 0; i--)
            {
                cases.Add(
                    Expression.Condition(
                        this.Visit(expression.When[i]),
                        this.Visit(expression.Then[i]),
                        cases.Last()));
            }

            return cases.Last();
        }
        public override void Visit(DbCaseExpression e)
        {
            Check.NotNull(e, "e");

            Begin(e);
            Dump(e.When, "Whens", "When");
            Dump(e.Then, "Thens", "Then");
            Dump(e.Else, "Else");
        }
Example #3
0
 public override void Visit(DbCaseExpression expression)
 {
     throw new NotSupportedException("Visit(\"DbCaseExpression\") is not supported.");
 }
Example #4
0
 /// <summary>
 /// Visits the <see cref="DbCaseExpression"/>.
 /// </summary>
 /// <param name="expression">The expression.</param>
 public abstract void Visit(DbCaseExpression expression);
 public override void Visit(DbCaseExpression e)
 {
     VisitExprKind(e.ExpressionKind);
     _key.Append('(');
     for (var idx = 0; idx < e.When.Count; idx++)
     {
         _key.Append("WHEN:(");
         e.When[idx].Accept(this);
         _key.Append(")THEN:(");
         e.Then[idx].Accept(this);
     }
     _key.Append("ELSE:(");
     e.Else.Accept(this);
     _key.Append("))");
 }
        /// <summary>
        ///     Visitor pattern method for <see cref="DbCaseExpression" />.
        /// </summary>
        /// <param name="expression"> The DbCaseExpression that is being visited. </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="expression" />
        ///     is null
        /// </exception>
        public override void Visit(DbCaseExpression expression)
        {
            // #433613: PreSharp warning 56506: Parameter 'expression' to this public method must be validated: A null-dereference can occur here.
            Check.NotNull(expression, "expression");

            VisitExpressionList(expression.When);
            VisitExpressionList(expression.Then);
            VisitExpression(expression.Else);
        }
 public override void Visit(DbCaseExpression expression)
 {
     Contract.Requires(expression != null);
 }
 public override void Visit(DbCaseExpression expression) { }
        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 (this.doNotProcess)
            {
                return(null);
            }

            if (this.extent.BuiltInTypeKind != BuiltInTypeKind.EntitySet ||
                this.extent.EntityContainer.DataSpace != DataSpace.CSpace)
            {
                this.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.
            //
            EntitySet targetSet = (EntitySet)this.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)
            {
                this.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 (AssociationSet 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)
                {
                    EntityType 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)
            {
                this.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.
            //
            DbProjectExpression            entityProject = (DbProjectExpression)viewConstructor;
            List <DbNewInstanceExpression> 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
                DbCaseExpression discriminatedConstructor = (DbCaseExpression)entityProject.Projection;
                conditions = new List <DbExpression>(discriminatedConstructor.When.Count);
                for (int 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);
            }

            bool rebuildView = false;

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

                List <DbRelatedEntityRef> 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.
                    //
                    List <DbExpression> whens = new List <DbExpression>(conditions.Count);
                    List <DbExpression> thens = new List <DbExpression>(conditions.Count);
                    for (int 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
            this.doNotProcess = true;
            return(result);
        }
 public override void Visit(DbCaseExpression expression)
 {
     throw new NotImplementedException();
 }
Example #11
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);
        }
Example #12
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));
        }
 /// <summary>
 /// Visitor pattern method for <see cref="DbCaseExpression"/>.
 /// </summary>
 /// <param name="expression">The DbCaseExpression that is being visited.</param>
 /// <exception cref="ArgumentNullException"><paramref name="expression"/> is null</exception>
 public override void Visit(DbCaseExpression expression)
 {
     VisitExpressionList(expression.When);
     VisitExpressionList(expression.Then);
     VisitExpression(expression.Else);
 }
Example #14
0
 public override DbExpressionEntitySetInfo Visit(DbCaseExpression expression)
 {
     return(null);
 }
        /// <summary>
        ///     Visitor pattern method for <see cref="DbCaseExpression" />.
        /// </summary>
        /// <param name="expression"> The DbCaseExpression that is being visited. </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="expression" />
        ///     is null
        /// </exception>
        public override void Visit(DbCaseExpression expression)
        {
            Check.NotNull(expression, "expression");

            VisitExpressionList(expression.When);
            VisitExpressionList(expression.Then);
            VisitExpression(expression.Else);
        }
        /// <summary>
        /// Converts the DbExpression equivalent of:
        ///
        /// SELECT CASE
        ///     WHEN a._from0 THEN SUBTYPE1()
        ///     ...
        ///     WHEN a._from[n-2] THEN SUBTYPE_n-1()
        ///     ELSE SUBTYPE_n
        /// FROM
        ///     SELECT
        ///         b.C1..., b.Cn
        ///         CASE WHEN b.Discriminator = SUBTYPE1_Value THEN true ELSE false AS _from0
        ///         ...
        ///         CASE WHEN b.Discriminator = SUBTYPE_n_Value THEN true ELSE false AS _from[n-1]
        ///     FROM TSet AS b
        ///     WHERE b.Discriminator = SUBTYPE1_Value... OR x.Discriminator = SUBTYPE_n_Value
        /// AS a
        /// WHERE a._from0... OR a._from[n-1]
        ///
        /// into the DbExpression equivalent of the following, which is matched as a TPH discriminator
        /// by the <see cref="System.Data.Mapping.ViewGeneration.GeneratedView"/> class and so allows a <see cref="System.Data.Mapping.ViewGeneration.DiscriminatorMap"/>
        /// to be produced for the view, which would not otherwise be possible. Note that C1 through Cn
        /// are only allowed to be scalars or complex type constructors based on direct property references
        /// to the store entity set's scalar properties.
        ///
        /// SELECT CASE
        ///     WHEN y.Discriminator = SUBTTYPE1_Value THEN SUBTYPE1()
        ///     ...
        ///     WHEN y.Discriminator = SUBTYPE_n-1_Value THEN SUBTYPE_n-1()
        ///     ELSE SUBTYPE_n()
        /// FROM
        ///     SELECT x.C1..., x.Cn, Discriminator FROM TSet AS x
        ///     WHERE x.Discriminator = SUBTYPE1_Value... OR x.Discriminator = SUBTYPE_n_Value
        /// AS y
        ///
        /// </summary>
        private static DbExpression SimplifyNestedTphDiscriminator(DbExpression expression)
        {
            DbProjectExpression entityProjection    = (DbProjectExpression)expression;
            DbFilterExpression  booleanColumnFilter = (DbFilterExpression)entityProjection.Input.Expression;
            DbProjectExpression rowProjection       = (DbProjectExpression)booleanColumnFilter.Input.Expression;
            DbFilterExpression  discriminatorFilter = (DbFilterExpression)rowProjection.Input.Expression;

            List <DbExpression>         predicates         = FlattenOr(booleanColumnFilter.Predicate).ToList();
            List <DbPropertyExpression> 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);
            }

            List <string> predicateColumnNames = propertyPredicates.Select(px => px.Property.Name).ToList();

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

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

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

            for (int idx = 0; idx < rowConstructor.Arguments.Count; idx++)
            {
                string       propName  = resultRow.Properties[idx].Name;
                DbExpression columnVal = rowConstructor.Arguments[idx];
                if (predicateColumnNames.Contains(propName))
                {
                    if (columnVal.ExpressionKind != DbExpressionKind.Case)
                    {
                        return(null);
                    }
                    DbCaseExpression 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 != false)
                    {
                        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
            DbExpression newDiscriminatorPredicate = Helpers.BuildBalancedTreeInPlace <DbExpression>(new List <DbExpression>(inputPredicateMap.Values), (left, right) => DbExpressionBuilder.Or(left, right));

            discriminatorFilter = discriminatorFilter.Input.Filter(newDiscriminatorPredicate);

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

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

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

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

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

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

            return(result);
        }
        public override TReturn Visit(DbCaseExpression expression)
        {
            Check.NotNull(expression, "expression");

            throw ConstructNotSupportedException(expression);
        }
 public override void Visit(DbCaseExpression e)
 {
     Begin(e);
     Dump(e.When, "Whens", "When");
     Dump(e.Then, "Thens", "Then");
     Dump(e.Else, "Else");
 }
        internal static bool TryCreateDiscriminatorMap(
            EntitySet entitySet,
            DbExpression queryView,
            out DiscriminatorMap discriminatorMap)
        {
            discriminatorMap = (DiscriminatorMap)null;
            if (queryView.ExpressionKind != DbExpressionKind.Project)
            {
                return(false);
            }
            DbProjectExpression projectExpression = (DbProjectExpression)queryView;

            if (projectExpression.Projection.ExpressionKind != DbExpressionKind.Case)
            {
                return(false);
            }
            DbCaseExpression projection = (DbCaseExpression)projectExpression.Projection;

            if (projectExpression.Projection.ResultType.EdmType.BuiltInTypeKind != BuiltInTypeKind.EntityType || projectExpression.Input.Expression.ExpressionKind != DbExpressionKind.Filter)
            {
                return(false);
            }
            DbFilterExpression expression1         = (DbFilterExpression)projectExpression.Input.Expression;
            HashSet <object>   discriminatorDomain = new HashSet <object>();

            if (!ViewSimplifier.TryMatchDiscriminatorPredicate(expression1, (Action <DbComparisonExpression, object>)((equalsExp, discriminatorValue) => discriminatorDomain.Add(discriminatorValue))))
            {
                return(false);
            }
            List <KeyValuePair <object, EntityType> >    keyValuePairList     = new List <KeyValuePair <object, EntityType> >();
            Dictionary <EdmProperty, DbExpression>       propertyMap          = new Dictionary <EdmProperty, DbExpression>();
            Dictionary <RelProperty, DbExpression>       relPropertyMap       = new Dictionary <RelProperty, DbExpression>();
            Dictionary <EntityType, List <RelProperty> > typeToRelPropertyMap = new Dictionary <EntityType, List <RelProperty> >();
            DbPropertyExpression discriminator = (DbPropertyExpression)null;
            EdmProperty          edmProperty   = (EdmProperty)null;

            for (int index = 0; index < projection.When.Count; ++index)
            {
                DbExpression         expression2  = projection.When[index];
                DbExpression         then         = projection.Then[index];
                string               variableName = projectExpression.Input.VariableName;
                DbPropertyExpression property;
                object               key;
                if (!ViewSimplifier.TryMatchPropertyEqualsValue(expression2, variableName, out property, out key))
                {
                    return(false);
                }
                if (edmProperty == null)
                {
                    edmProperty = (EdmProperty)property.Property;
                }
                else if (edmProperty != property.Property)
                {
                    return(false);
                }
                discriminator = property;
                EntityType entityType;
                if (!DiscriminatorMap.TryMatchEntityTypeConstructor(then, propertyMap, relPropertyMap, typeToRelPropertyMap, out entityType))
                {
                    return(false);
                }
                keyValuePairList.Add(new KeyValuePair <object, EntityType>(key, entityType));
                discriminatorDomain.Remove(key);
            }
            EntityType entityType1;

            if (1 != discriminatorDomain.Count || projection.Else == null || !DiscriminatorMap.TryMatchEntityTypeConstructor(projection.Else, propertyMap, relPropertyMap, typeToRelPropertyMap, out entityType1))
            {
                return(false);
            }
            keyValuePairList.Add(new KeyValuePair <object, EntityType>(discriminatorDomain.Single <object>(), entityType1));
            if (!DiscriminatorMap.CheckForMissingRelProperties(relPropertyMap, typeToRelPropertyMap) || keyValuePairList.Select <KeyValuePair <object, EntityType>, object>((Func <KeyValuePair <object, EntityType>, object>)(map => map.Key)).Distinct <object>((IEqualityComparer <object>)TrailingSpaceComparer.Instance).Count <object>() != keyValuePairList.Count)
            {
                return(false);
            }
            discriminatorMap = new DiscriminatorMap(discriminator, keyValuePairList, propertyMap, relPropertyMap, entitySet);
            return(true);
        }
 /// <summary>
 ///     Visitor pattern method for DbCaseExpression.
 /// </summary>
 /// <param name="expression"> The DbCaseExpression that is being visited. </param>
 public abstract void Visit(DbCaseExpression expression);
            public override DbExpressionEntitySetInfo Visit(DbCaseExpression expression)
            {
                Check.NotNull(expression, "expression");

                return(null);
            }
		public override void Visit(DbCaseExpression expression)
		{
			throw new NotSupportedException("Visit(\"CaseExpression\") is not supported.");
		}
Example #23
0
        /// <summary>
        /// Implements the visitor pattern for <see cref="T:System.Data.Common.CommandTrees.DbCaseExpression"/>.
        /// </summary>
        /// <param name="expression">The <see cref="T:System.Data.Common.CommandTrees.DbCaseExpression"/> that is visited.</param>
        public override void Visit(DbCaseExpression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            foreach (DbExpression e in expression.When)
            {
                e.Accept(this);
            }

            foreach (DbExpression e in expression.Then)
            {
                e.Accept(this);
            }

            expression.Else.Accept(this);
        }
Example #24
0
 public override void Visit(DbCaseExpression expression)
 {
   if (expression == null) throw new ArgumentException("expression");
   VisitExpressionList(expression.When);
   VisitExpressionList(expression.Then);
   VisitExpression(expression.Else);
 }
 public override IPostgreSqlFragment Visit(DbCaseExpression expression)
 {
     throw new NotImplementedException();
 }