src/Shared/EntityFramework/Core/Mapping/ViewGeneration/DiscriminatorMap.cs
// <summary>
// Determines whether the given query view matches the discriminator map pattern.
// </summary>
Determines whether the given query view matches the discriminator map pattern.
Determines whether the given query view matches the discriminator map pattern .
internal static bool TryCreateDiscriminatorMap(EntitySet entitySet, DbExpression queryView, out DiscriminatorMap discriminatorMap)
        {
            discriminatorMap = null;
            if (queryView.ExpressionKind
                != DbExpressionKind.Project)
            {
                return false;
            }
            var project = (DbProjectExpression)queryView;
            if (project.Projection.ExpressionKind
                != DbExpressionKind.Case)
            {
                return false;
            }
            var caseExpression = (DbCaseExpression)project.Projection;
            if (project.Projection.ResultType.EdmType.BuiltInTypeKind
                != BuiltInTypeKind.EntityType)
            {
                return false;
            }
            if (project.Input.Expression.ExpressionKind
                != DbExpressionKind.Filter)
            {
                return false;
            }
            var filterExpression = (DbFilterExpression)project.Input.Expression;
            var discriminatorDomain = new HashSet<object>();
            if (
                !ViewSimplifier.TryMatchDiscriminatorPredicate(
                    filterExpression, (equalsExp, discriminatorValue) => discriminatorDomain.Add(discriminatorValue)))
            {
                return false;
            }
            var typeMap = new List<KeyValuePair<object, EntityType>>();
            var propertyMap = new Dictionary<EdmProperty, DbExpression>();
            var relPropertyMap = new Dictionary<RelProperty, DbExpression>();
            var typeToRelPropertyMap = new Dictionary<EntityType, List<RelProperty>>();
            DbPropertyExpression discriminator = null;
            EdmProperty discriminatorProperty = null;
            for (var i = 0; i < caseExpression.When.Count; i++)
            {
                var when = caseExpression.When[i];
                var then = caseExpression.Then[i];
                var projectionVariableName = project.Input.VariableName;
                DbPropertyExpression currentDiscriminator;
                object discriminatorValue;
                if (
                    !ViewSimplifier.TryMatchPropertyEqualsValue(
                        when, projectionVariableName, out currentDiscriminator, out discriminatorValue))
                {
                    return false;
                }
                if (null == discriminatorProperty)
                {
                    discriminatorProperty = (EdmProperty)currentDiscriminator.Property;
                }
                else if (discriminatorProperty != currentDiscriminator.Property)
                {
                    return false;
                }
                discriminator = currentDiscriminator;
                EntityType currentType;
                if (!TryMatchEntityTypeConstructor(then, propertyMap, relPropertyMap, typeToRelPropertyMap, out currentType))
                {
                    return false;
                }
                typeMap.Add(new KeyValuePair<object, EntityType>(discriminatorValue, currentType));
                discriminatorDomain.Remove(discriminatorValue);
            }
            if (1 != discriminatorDomain.Count)
            {
                return false;
            }
            EntityType elseType;
            if (null == caseExpression.Else
                ||
                !TryMatchEntityTypeConstructor(caseExpression.Else, propertyMap, relPropertyMap, typeToRelPropertyMap, out elseType))
            {
                return false;
            }
            typeMap.Add(new KeyValuePair<object, EntityType>(discriminatorDomain.Single(), elseType));
            if (!CheckForMissingRelProperties(relPropertyMap, typeToRelPropertyMap))
            {
                return false;
            }
            var discriminatorValues = typeMap.Select(map => map.Key);
            var uniqueValueCount = discriminatorValues.Distinct(TrailingSpaceComparer.Instance).Count();
            var valueCount = typeMap.Count;
            if (uniqueValueCount != valueCount)
            {
                return false;
            }
            discriminatorMap = new DiscriminatorMap(discriminator, typeMap, propertyMap, relPropertyMap, entitySet);
            return true;
        }
internal static bool TryCreateDiscriminatorMap ( EntitySet entitySet , DbExpression queryView , out DiscriminatorMap discriminatorMap ) { discriminatorMap = null ; if ( queryView . ExpressionKind != DbExpressionKind . Project ) { return false ; } var project = ( DbProjectExpression ) queryView ; if ( project . Projection . ExpressionKind != DbExpressionKind . Case ) { return false ; } var caseExpression = ( DbCaseExpression ) project . Projection ; if ( project . Projection . ResultType . EdmType . BuiltInTypeKind != BuiltInTypeKind . EntityType ) { return false ; } if ( project . Input . Expression . ExpressionKind != DbExpressionKind . Filter ) { return false ; } var filterExpression = ( DbFilterExpression ) project . Input . Expression ; var discriminatorDomain = new HashSet < object > ( ) ; if ( ! ViewSimplifier . TryMatchDiscriminatorPredicate ( filterExpression , ( equalsExp , discriminatorValue ) => discriminatorDomain . Add ( discriminatorValue ) ) ) { return false ; } var typeMap = new List < KeyValuePair < object , EntityType > > ( ) ; var propertyMap = new Dictionary < EdmProperty , DbExpression > ( ) ; var relPropertyMap = new Dictionary < RelProperty , DbExpression > ( ) ; var typeToRelPropertyMap = new Dictionary < EntityType , List < RelProperty > > ( ) ; DbPropertyExpression discriminator = null ; EdmProperty discriminatorProperty = null ; for ( var i = 0 ; i < caseExpression . When . Count ; i ++ ) { var when = caseExpression . When [ i ] ; var then = caseExpression . Then [ i ] ; var projectionVariableName = project . Input . VariableName ; DbPropertyExpression currentDiscriminator ; object discriminatorValue ; if ( ! ViewSimplifier . TryMatchPropertyEqualsValue ( when , projectionVariableName , out currentDiscriminator , out discriminatorValue ) ) { return false ; } if ( null == discriminatorProperty ) { discriminatorProperty = ( EdmProperty ) currentDiscriminator . Property ; } else if ( discriminatorProperty != currentDiscriminator . Property ) { return false ; } discriminator = currentDiscriminator ; EntityType currentType ; if ( ! TryMatchEntityTypeConstructor ( then , propertyMap , relPropertyMap , typeToRelPropertyMap , out currentType ) ) { return false ; } typeMap . Add ( new KeyValuePair < object , EntityType > ( discriminatorValue , currentType ) ) ; discriminatorDomain . Remove ( discriminatorValue ) ; } if ( 1 != discriminatorDomain . Count ) { return false ; } EntityType elseType ; if ( null == caseExpression . Else || ! TryMatchEntityTypeConstructor ( caseExpression . Else , propertyMap , relPropertyMap , typeToRelPropertyMap , out elseType ) ) { return false ; } typeMap . Add ( new KeyValuePair < object , EntityType > ( discriminatorDomain . Single ( ) , elseType ) ) ; if ( ! CheckForMissingRelProperties ( relPropertyMap , typeToRelPropertyMap ) ) { return false ; } var discriminatorValues = typeMap . Select ( map => map . Key ) ; var uniqueValueCount = discriminatorValues . Distinct ( TrailingSpaceComparer . Instance ) . Count ( ) ; var valueCount = typeMap . Count ; if ( uniqueValueCount != valueCount ) { return false ; } discriminatorMap = new DiscriminatorMap ( discriminator , typeMap , propertyMap , relPropertyMap , entitySet ) ; return true ; }
Determines whether the given query view matches the discriminator map pattern.
Determines whether the given query view matches the discriminator map pattern .
// determine value domain by walking filter // must be the same discriminator in every case // right hand side must be entity type constructor // remember type + discriminator value // remove discriminator value from domain // make sure only one member of discriminator domain remains... // check default case // Account for cases where some type in the hierarchy specifies a rel-property, but another // type in the hierarchy does not // since the store may right-pad strings, ensure discriminator values are unique in their trimmed // form
entitySet
EntitySet
queryView
DbExpression
DiscriminatorMap
out