private DbExpression GenerateScalarResultMappingView(DbExpression storeFunctionInvoke) { DbExpression queryExpression = storeFunctionInvoke; CollectionType functionImportReturnType; if (!MetadataHelper.TryGetFunctionImportReturnCollectionType(this.FunctionImport, 0, out functionImportReturnType)) { Debug.Fail("Failed to get the result type of the function import."); } Debug.Assert(TypeSemantics.IsCollectionType(queryExpression.ResultType), "Store function must be TVF (collection expected)."); var collectionType = (CollectionType)queryExpression.ResultType.EdmType; Debug.Assert(TypeSemantics.IsRowType(collectionType.TypeUsage), "Store function must be TVF (collection of rows expected)."); var rowType = (RowType)collectionType.TypeUsage.EdmType; var column = rowType.Properties[0]; Func <DbExpression, DbExpression> scalarView = (DbExpression row) => { var propertyAccess = row.Property(column); if (TypeSemantics.IsEqual(functionImportReturnType.TypeUsage, column.TypeUsage)) { return(propertyAccess); } else { return(propertyAccess.CastTo(functionImportReturnType.TypeUsage)); } }; queryExpression = queryExpression.Select(row => scalarView(row)); return(queryExpression); }
internal override DbExpression AsCqt(bool isTopLevel) { // The FROM part: // - build a tree of binary joins out of the inputs (this.Children). // - update each child block with its relative position in the join tree, // so that QualifiedSlot and QualifiedCellIdBoolean objects could find their // designated block areas inside the cumulative join row passed into their AsCqt(row) method. CqlBlock leftmostBlock = this.Children[0]; DbExpression left = leftmostBlock.AsCqt(false); List <string> joinTreeCtxParentQualifiers = new List <string>(); for (int i = 1; i < this.Children.Count; ++i) { // Join the current left expression (a tree) to the current right block. CqlBlock rightBlock = this.Children[i]; DbExpression right = rightBlock.AsCqt(false); Func <DbExpression, DbExpression, DbExpression> joinConditionFunc = m_onClauses[i - 1].AsCqt; DbJoinExpression join; switch (m_opType) { case CellTreeOpType.FOJ: join = left.FullOuterJoin(right, joinConditionFunc); break; case CellTreeOpType.IJ: join = left.InnerJoin(right, joinConditionFunc); break; case CellTreeOpType.LOJ: join = left.LeftOuterJoin(right, joinConditionFunc); break; default: Debug.Fail("Unknown operator"); return(null); } if (i == 1) { // Assign the joinTreeContext to the leftmost block. leftmostBlock.SetJoinTreeContext(joinTreeCtxParentQualifiers, join.Left.VariableName); } else { // Update the joinTreeCtxParentQualifiers. // Note that all blocks that already participate in the left expression tree share the same copy of the joinTreeContext. joinTreeCtxParentQualifiers.Add(join.Left.VariableName); } // Assign the joinTreeContext to the right block. rightBlock.SetJoinTreeContext(joinTreeCtxParentQualifiers, join.Right.VariableName); left = join; } // The SELECT part. return(left.Select(row => GenerateProjectionCqt(row, false))); }
internal override DbExpression AsCqt(bool isTopLevel) { DbExpression source = this.Children[0].AsCqt(false); if (!BoolExpression.EqualityComparer.Equals(this.WhereClause, BoolExpression.True)) { source = (DbExpression)source.Where((Func <DbExpression, DbExpression>)(row => this.WhereClause.AsCqt(row))); } return((DbExpression)source.Select <DbExpression>((Func <DbExpression, DbExpression>)(row => this.GenerateProjectionCqt(row, isTopLevel)))); }
internal override DbExpression AsCqt(bool isTopLevel) { DbExpression source = (DbExpression)this.m_extent.Scan(); if (!BoolExpression.EqualityComparer.Equals(this.WhereClause, BoolExpression.True)) { source = (DbExpression)source.Where((Func <DbExpression, DbExpression>)(row => this.WhereClause.AsCqt(row))); } DbExpression dbExpression = (DbExpression)source.Select <DbExpression>((Func <DbExpression, DbExpression>)(row => this.GenerateProjectionCqt(row, isTopLevel))); if (this.m_selectDistinct == CellQuery.SelectDistinct.Yes) { dbExpression = (DbExpression)dbExpression.Distinct(); } return(dbExpression); }
internal override DbExpression AsCqt(bool isTopLevel) { Debug.Assert(m_caseSlotInfo.OutputMember != null, "We only construct real slots not boolean slots"); // The FROM part: FROM (childBlock) Debug.Assert(Children.Count == 1, "CaseCqlBlock can have exactly one child."); CqlBlock childBlock = this.Children[0]; DbExpression cqt = childBlock.AsCqt(false); // Get the WHERE part only when the expression is not simply TRUE. if (!BoolExpression.EqualityComparer.Equals(this.WhereClause, BoolExpression.True)) { cqt = cqt.Where(row => this.WhereClause.AsCqt(row)); } // The SELECT part. return(cqt.Select(row => GenerateProjectionCqt(row, isTopLevel))); }
internal override DbExpression AsCqt(bool isTopLevel) { CqlBlock child1 = this.Children[0]; DbExpression dbExpression = child1.AsCqt(false); List <string> stringList = new List <string>(); for (int index = 1; index < this.Children.Count; ++index) { CqlBlock child2 = this.Children[index]; DbExpression right = child2.AsCqt(false); Func <DbExpression, DbExpression, DbExpression> joinCondition = new Func <DbExpression, DbExpression, DbExpression>(this.m_onClauses[index - 1].AsCqt); DbJoinExpression dbJoinExpression; switch (this.m_opType) { case CellTreeOpType.FOJ: dbJoinExpression = dbExpression.FullOuterJoin(right, joinCondition); break; case CellTreeOpType.LOJ: dbJoinExpression = dbExpression.LeftOuterJoin(right, joinCondition); break; case CellTreeOpType.IJ: dbJoinExpression = dbExpression.InnerJoin(right, joinCondition); break; default: return((DbExpression)null); } if (index == 1) { child1.SetJoinTreeContext((IList <string>)stringList, dbJoinExpression.Left.VariableName); } else { stringList.Add(dbJoinExpression.Left.VariableName); } child2.SetJoinTreeContext((IList <string>)stringList, dbJoinExpression.Right.VariableName); dbExpression = (DbExpression)dbJoinExpression; } return((DbExpression)dbExpression.Select <DbExpression>((Func <DbExpression, DbExpression>)(row => this.GenerateProjectionCqt(row, false)))); }
internal override DbExpression AsCqt(bool isTopLevel) { // Get the FROM part. DbExpression cqt = m_extent.Scan(); // Get the WHERE part only when the expression is not simply TRUE. if (!BoolExpression.EqualityComparer.Equals(WhereClause, BoolExpression.True)) { cqt = cqt.Where(row => WhereClause.AsCqt(row)); } // The SELECT/DISTINCT part. cqt = cqt.Select(row => GenerateProjectionCqt(row, isTopLevel)); if (m_selectDistinct == CellQuery.SelectDistinct.Yes) { cqt = cqt.Distinct(); } return(cqt); }
private DbExpression GenerateScalarResultMappingView( DbExpression storeFunctionInvoke) { DbExpression source = storeFunctionInvoke; CollectionType functionImportReturnType; MetadataHelper.TryGetFunctionImportReturnCollectionType(this.FunctionImport, 0, out functionImportReturnType); EdmProperty column = ((RowType)((CollectionType)source.ResultType.EdmType).TypeUsage.EdmType).Properties[0]; Func <DbExpression, DbExpression> scalarView = (Func <DbExpression, DbExpression>)(row => { DbPropertyExpression propertyExpression = row.Property(column); if (TypeSemantics.IsEqual(functionImportReturnType.TypeUsage, column.TypeUsage)) { return((DbExpression)propertyExpression); } return((DbExpression)propertyExpression.CastTo(functionImportReturnType.TypeUsage)); }); return((DbExpression)source.Select <DbExpression>((Func <DbExpression, DbExpression>)(row => scalarView(row)))); }
/// <summary> /// Returns the update or query view for an Extent as a /// string. /// There are a series of steps that we go through for discovering a view for an extent. /// To start with we assume that we are working with Generated Views. To find out the /// generated view we go to the ObjectItemCollection and see if it is not-null. If the ObjectItemCollection /// is non-null, we get the view generation assemblies that it might have cached during the /// Object metadata discovery.If there are no view generation assemblies we switch to the /// runtime view generation strategy. If there are view generation assemblies, we get the list and /// go through them and see if there are any assemblies that are there from which we have not already loaded /// the views. We collect the views from assemblies that we have not already collected from earlier. /// If the ObjectItemCollection is null and we are in the view generation mode, that means that /// the query or update is issued from the Value layer and this is the first time view has been asked for. /// The compile time view gen for value layer queries will work for very simple scenarios. /// If the users wants to get the performance benefit, they should call MetadataWorkspace.LoadFromAssembly. /// At this point we go through the referenced assemblies of the entry assembly( this wont work for Asp.net /// or if the viewgen assembly was not referenced by the executing application). /// and try to see if there were any view gen assemblies. If there are, we collect the views for all extents. /// Once we have all the generated views gathered, we try to get the view for the extent passed in. /// If we find one we will return it. If we can't find one an exception will be thrown. /// If there were no view gen assemblies either in the ObjectItemCollection or in the list of referenced /// assemblies of calling assembly, we change the mode to runtime view generation and will continue to /// be in that mode for the rest of the lifetime of the mapping item collection. /// </summary> internal GeneratedView GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace, StorageMappingItemCollection storageMappingItemCollection) { //First check if we have collected a view from user-defined query views //Dont need to worry whether to generate Query view or update viw, because that is relative to the extent. GeneratedView view; if (TryGetUserDefinedQueryView(extent, out view)) { return(view); } //If this is a foreign key association, manufacture a view on the fly. if (extent.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) { AssociationSet aSet = (AssociationSet)extent; if (aSet.ElementType.IsForeignKey) { if (m_config.IsViewTracing) { Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); Helpers.FormatTraceLine("================= Generating FK Query View for: {0} =================", aSet.Name); Helpers.StringTraceLine(String.Empty); Helpers.StringTraceLine(String.Empty); } // Although we expose a collection of constraints in the API, there is only ever one constraint. Debug.Assert(aSet.ElementType.ReferentialConstraints.Count == 1, "aSet.ElementType.ReferentialConstraints.Count == 1"); ReferentialConstraint rc = aSet.ElementType.ReferentialConstraints.Single(); EntitySet dependentSet = aSet.AssociationSetEnds[rc.ToRole.Name].EntitySet; EntitySet principalSet = aSet.AssociationSetEnds[rc.FromRole.Name].EntitySet; DbExpression qView = dependentSet.Scan(); // Introduce an OfType view if the dependent end is a subtype of the entity set EntityType dependentType = MetadataHelper.GetEntityTypeForEnd((AssociationEndMember)rc.ToRole); EntityType principalType = MetadataHelper.GetEntityTypeForEnd((AssociationEndMember)rc.FromRole); if (dependentSet.ElementType.IsBaseTypeOf(dependentType)) { qView = qView.OfType(TypeUsage.Create(dependentType)); } if (rc.FromRole.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne) { // Filter out instances with existing relationships. qView = qView.Where(e => { DbExpression filter = null; foreach (EdmProperty fkProp in rc.ToProperties) { DbExpression notIsNull = e.Property(fkProp).IsNull().Not(); filter = null == filter ? notIsNull : filter.And(notIsNull); } return(filter); }); } qView = qView.Select(e => { List <DbExpression> ends = new List <DbExpression>(); foreach (AssociationEndMember end in aSet.ElementType.AssociationEndMembers) { if (end.Name == rc.ToRole.Name) { var keyValues = new List <KeyValuePair <string, DbExpression> >(); foreach (EdmMember keyMember in dependentSet.ElementType.KeyMembers) { keyValues.Add(e.Property((EdmProperty)keyMember)); } ends.Add(dependentSet.RefFromKey(DbExpressionBuilder.NewRow(keyValues), dependentType)); } else { // Manufacture a key using key values. var keyValues = new List <KeyValuePair <string, DbExpression> >(); foreach (EdmMember keyMember in principalSet.ElementType.KeyMembers) { int offset = rc.FromProperties.IndexOf((EdmProperty)keyMember); keyValues.Add(e.Property(rc.ToProperties[offset])); } ends.Add(principalSet.RefFromKey(DbExpressionBuilder.NewRow(keyValues), principalType)); } } return(TypeUsage.Create(aSet.ElementType).New(ends)); }); return(GeneratedView.CreateGeneratedViewForFKAssociationSet(aSet, aSet.ElementType, new DbQueryCommandTree(workspace, DataSpace.SSpace, qView), storageMappingItemCollection, m_config)); } } // If no User-defined QV is found, call memoized View Generation procedure. Dictionary <EntitySetBase, GeneratedView> generatedViews = m_generatedViewsMemoizer.Evaluate(extent.EntityContainer); if (!generatedViews.TryGetValue(extent, out view)) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Mapping_Views_For_Extent_Not_Generated( (extent.EntityContainer.DataSpace == DataSpace.SSpace)?"Table":"EntitySet", extent.Name)); } return(view); }