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); }
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); }