Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / ExpressionCopier.cs / 4 / ExpressionCopier.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....], [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Data.Common; using System.Data.Metadata.Edm; using System.Data.Common.CommandTrees; namespace System.Data.Common.CommandTrees.Internal { ////// Clones an expression tree /// internal class ExpressionCopier : DbExpressionVisitor{ /// /// The MetadataMapper class is a helper class that logically translates /// metadata constructs from one space to another. The objects that are translated /// include /// Types /// Properties /// Methods /// Functions /// Extents /// EntitySets /// The default implementation is to simply return the specified metadata instance /// (an 'identity' mapping) /// protected class MetadataMapper { internal static readonly MetadataMapper IdentityMapper = new MetadataMapper(); internal MetadataMapper() {} internal virtual EdmType Map(EdmType s) { return s; } internal virtual EntitySetBase Map(EntitySetBase e) { return e; } internal virtual EntitySet Map(EntitySet e) { return e; } internal virtual EdmFunction Map(EdmFunction f) { return f; } internal virtual NavigationProperty Map(NavigationProperty p) { return p; } internal virtual EdmProperty Map(EdmProperty p) { return p; } internal virtual RelationshipEndMember Map(RelationshipEndMember m) { return m; } internal virtual TypeUsage Map(TypeUsage t) { return t; } #if METHOD_EXPRESSION internal virtual MethodMetadata Map(MethodMetadata m) { return m; } #endif } private class WorkspaceMapper : MetadataMapper { private MetadataWorkspace _metadata; private Dictionary_transientTypes = new Dictionary (); internal WorkspaceMapper(MetadataWorkspace destinationWorkspace) : base() { _metadata = destinationWorkspace; } #region MetadataMapper Overrides internal override EdmType Map(EdmType type) { EdmType retType = null; if (BuiltInTypeKind.RefType == type.BuiltInTypeKind) { RefType refType = (RefType)type; retType = new RefType((EntityType)Map(refType.ElementType)); } else if (BuiltInTypeKind.CollectionType == type.BuiltInTypeKind) { CollectionType collectionType = (CollectionType)type; retType = new CollectionType(Map(collectionType.TypeUsage)); } else if (BuiltInTypeKind.RowType == type.BuiltInTypeKind) { RowType rowType = (RowType)type; List columns = new List (); foreach (EdmProperty p in rowType.Properties) { columns.Add(new EdmProperty(p.Name, Map(p.TypeUsage))); } RowType newRowType = new RowType(columns, rowType.InitializerMetadata); retType = newRowType; } else { if (!_metadata.TryGetType(type.Name, type.NamespaceName, type.DataSpace, out retType) || null == retType) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_TypeNotFound(TypeHelpers.GetFullName(type))); } } return retType; } internal override EntitySetBase Map(EntitySetBase e) { EntityContainer container; if (_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container)) { EntitySetBase extent = null; if (container.BaseEntitySets.TryGetValue(e.Name, false, out extent) && extent != null) { return extent; } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name)); } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name)); } internal override EntitySet Map(EntitySet e) { EntityContainer container; if(_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container)) { EntitySetBase set = null; if (container.BaseEntitySets.TryGetValue(e.Name, false, out set)) { EntitySet entitySet = set as EntitySet; if (entitySet != null) { return entitySet; } } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name)); } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name)); } internal override EdmFunction Map(EdmFunction f) { TypeUsage[] paramTypes = new TypeUsage[f.Parameters.Count]; int idx = 0; foreach (FunctionParameter p in f.Parameters) { paramTypes[idx] = Map(p.TypeUsage); idx++; } EdmFunction retFunc = null; if( _metadata.TryGetFunction(f.Name, f.NamespaceName, paramTypes, false, f.DataSpace, out retFunc) && retFunc != null) { return retFunc; } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_FunctionNotFound(TypeHelpers.GetFullName(f))); } internal override NavigationProperty Map(NavigationProperty prop) { NavigationProperty retProp; if (!TryMapMember(prop, out retProp)) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType))); } return retProp; } internal override EdmProperty Map(EdmProperty prop) { EdmProperty retProp; if (!TryMapMember(prop, out retProp)) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType))); } return retProp; } internal override RelationshipEndMember Map(RelationshipEndMember end) { RelationshipEndMember retEnd; if (!TryMapMember(end, out retEnd)) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EndNotFound(end.Name, TypeHelpers.GetFullName(end.DeclaringType))); } return retEnd; } private bool TryMapMember (TMemberType prop, out TMemberType foundProp) where TMemberType : EdmMember { foundProp = null; StructuralType mappedType = Map(prop.DeclaringType) as StructuralType; if (mappedType != null) { EdmMember foundMember = null; if (mappedType.Members.TryGetValue(prop.Name, false, out foundMember)) { foundProp = foundMember as TMemberType; } } return (foundProp != null); } #if METHOD_EXPRESSION internal override MethodMetadata Map(MethodMetadata meth) { MethodMetadata retMethod = null; List mappedParamTypes = new List (); foreach (IParameterMetadata methParam in meth.Parameters) { mappedParamTypes.Add(this.Map(methParam.Type)); } TypeMetadata mappedType = this.Map(meth.DefiningType); foreach (MemberMetadata member in mappedType.GetMemberByName(meth.Name)) { // Ignore the member if: // - It's not a method, OR // - It's IsStatic property doesn't match, OR // - It doesn't declare the right number of parameters. MethodMetadata mappedMeth = member as MethodMetadata; if( null == mappedMeth || mappedMeth.IsStatic != meth.IsStatic || mappedMeth.Parameters.Count != mappedParamTypes.Count) { continue; } // Assume that the method matches, which is correct for the case // where the required method and this method both declare no parameters. bool paramMatch = true; for (int idx = 0; idx < mappedParamTypes.Count; idx++) { // If the type of any parameter to the method under consideration // does not match the type of the corresponding parameter from the // source method, then this cannot be the correct destination method. if (!mappedParamTypes[idx].Equals(mappedMeth.Parameters[idx].Type)) { paramMatch = false; break; } } // If any of the parameter types didn't match then move on. if (!paramMatch) { continue; } // This is the required method. retMethod = mappedMeth; break; } if (null == retMethod) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_MethodNotFound(meth.Name, mappedType.FullName)); } return retMethod; } #endif internal override TypeUsage Map(TypeUsage type) { // // If the target metatadata workspace contains the same type instances, then the type does not // need to be 'mapped' and the same TypeUsage instance may be returned. This can happen if the // target workspace and the workspace of the source Command Tree are using the same ItemCollection. // EdmType retEdmType = Map(type.EdmType); if (object.ReferenceEquals(retEdmType, type.EdmType)) { return type; } // // Retrieve the Facets from this type usage so that // 1) They can be used to map the type if it is a primitive type // 2) They can be applied to the new type usage that references the mapped type // Facet[] facets = new Facet[type.Facets.Count]; int idx = 0; foreach (Facet f in type.Facets) { facets[idx] = f; idx++; } return TypeUsage.Create(retEdmType, facets); } #endregion } private MetadataMapper _mapper; private DbCommandTree _commandTree; protected DbCommandTree CommandTree { get { return this._commandTree; } } protected ExpressionCopier(DbCommandTree commandTree, MetadataMapper mapper) { _commandTree = commandTree; _mapper = mapper; } private static MetadataMapper GetMapper(MetadataWorkspace source, MetadataWorkspace destination) { ItemCollection mappingItemCollection = source.GetItemCollection(DataSpace.CSSpace); ItemCollection destinationMappingItemCollection = destination.GetItemCollection(DataSpace.CSSpace); if (!object.ReferenceEquals(mappingItemCollection, destinationMappingItemCollection)) { EntityBid.Trace(" Using cross-workspace metadata mapper\n"); return new WorkspaceMapper(destination); } EntityBid.Trace(" Using identity metadata mapper\n"); return MetadataMapper.IdentityMapper; } internal static DbExpression Copy(DbCommandTree destination, DbExpression expression) { Debug.Assert(destination != null, "Destination Command Tree is null"); Debug.Assert(expression != null, "DbExpression is null"); using(new EntityBid.ScopeAuto(" destination=%d#", destination.ObjectId)) { EntityBid.Trace(" expression=%d#, %d{cqt.DbExpressionKind}\n", DbExpression.GetObjectId(expression), DbExpression.GetExpressionKind(expression)); ExpressionCopier copier = new ExpressionCopier(destination, GetMapper(expression.CommandTree.MetadataWorkspace, destination.MetadataWorkspace)); return copier.VisitExpr(expression); } } public List VisitList (IList exprList) where T: DbExpression { List retList = null; if (exprList != null) { retList = new List (); for (int idx = 0; idx < exprList.Count; idx++) { retList.Add((T)this.VisitExpr(exprList[idx])); } } return retList; } public List VisitExprList(IList exprList) { return VisitList (exprList); } public DbExpressionBinding VisitBinding(DbExpressionBinding b) { DbExpression newExpr = VisitExpr(b.Expression); return this._commandTree.CreateExpressionBinding(newExpr, b.VariableName); } public DbGroupExpressionBinding VisitGroupExpressionBinding(DbGroupExpressionBinding gb) { DbExpression newExpr = VisitExpr(gb.Expression); return this._commandTree.CreateGroupExpressionBinding(newExpr, gb.VariableName, gb.GroupVariableName); } public List VisitBindingList(IList bindingList) { List retList = null; if (bindingList != null) { retList = new List (); for (int idx = 0; idx < bindingList.Count; idx++) { retList.Add(this.VisitBinding(bindingList[idx])); } } return retList; } public List VisitSortOrder(IList sortOrder) { List skeys = new List (); for(int idx = 0; idx < sortOrder.Count; idx++) { DbSortClause s = sortOrder[idx]; DbExpression keyExpr = VisitExpr(s.Expression); bool asc = s.Ascending; if(!string.IsNullOrEmpty(s.Collation)) { skeys.Add(_commandTree.CreateSortClause(keyExpr, asc, s.Collation)); } else { skeys.Add(_commandTree.CreateSortClause(keyExpr, asc)); } } return skeys; } public virtual DbFunctionAggregate VisitFunctionAggregate(DbFunctionAggregate a) { if (a.Distinct) { return _commandTree.CreateDistinctFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0])); } else { return _commandTree.CreateFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0])); } } #if ENABLE_NESTAGGREGATE public virtual NestAggregate VisitNestAggregate(NestAggregate a) { return _commandTree.CreateNestAggregate(VisitExpr(a.Arguments[0])); } #endif public DbAggregate VisitAggregate(DbAggregate a) { DbFunctionAggregate funcA = a as DbFunctionAggregate; if (funcA != null) { return VisitFunctionAggregate(funcA); } #if ENABLE_NESTAGGREGATE else if (a is NestAggregate) { return VisitNestAggregate(a as NestAggregate); } #endif return null; } public DbExpression VisitExpr(DbExpression expr) { if (expr == null) { return null; } return expr.Accept (this); } #region DbExpressionVisitor Members public override DbExpression Visit(DbExpression e) { throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_General_UnsupportedExpression(e.GetType().FullName)); } public override DbExpression Visit(DbConstantExpression e) { return _commandTree.CreateConstantExpression(e.Value, _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbNullExpression e) { return _commandTree.CreateNullExpression(_mapper.Map(e.ResultType)); } public override DbExpression Visit(DbVariableReferenceExpression e) { return _commandTree.CreateVariableReferenceExpression(e.VariableName, _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbParameterReferenceExpression e) { return _commandTree.CreateParameterReferenceExpression(e.ParameterName); } public override DbExpression Visit(DbFunctionExpression e) { if (e.IsLambda) { List > formals = new List >(); for(int idx = 0; idx < e.Function.Parameters.Count; idx++) { FunctionParameter formal = e.Function.Parameters[idx]; formals.Add(new KeyValuePair (formal.Name, _mapper.Map(formal.TypeUsage))); } return _commandTree.CreateLambdaFunctionExpression(formals, VisitExpr(e.LambdaBody), VisitExprList(e.Arguments)); } else { return _commandTree.CreateFunctionExpression(_mapper.Map(e.Function), VisitExprList(e.Arguments)); } } #if METHOD_EXPRESSION public override Expression Visit(MethodExpression e) { if (e.Method.IsStatic) { return _commandTree.CreateStaticMethodExpression(_mapper.Map(e.Method), VisitExprList(e.Arguments)); } else { return _commandTree.CreateInstanceMethodExpression(_mapper.Map(e.Method), VisitExpr(e.Instance), VisitExprList(e.Arguments)); } } #endif public override DbExpression Visit(DbPropertyExpression e) { DbExpression instanceCopy = VisitExpr(e.Instance); if (Helper.IsNavigationProperty(e.Property)) { return _commandTree.CreatePropertyExpression(_mapper.Map((NavigationProperty)e.Property), instanceCopy); } else if (Helper.IsEdmProperty(e.Property)) { return _commandTree.CreatePropertyExpression(_mapper.Map((EdmProperty)e.Property), instanceCopy); } else { Debug.Assert(e.Property is RelationshipEndMember, "Invalid DbPropertyExpression - Property is not EdmProperty, NavigationProperty or RelationshipEndMember"); return _commandTree.CreatePropertyExpression(_mapper.Map((RelationshipEndMember)e.Property), instanceCopy); } } public override DbExpression Visit(DbComparisonExpression e) { DbExpression left = VisitExpr(e.Left); DbExpression right = VisitExpr(e.Right); switch (e.ExpressionKind) { case DbExpressionKind.Equals: return _commandTree.CreateEqualsExpression(left, right); case DbExpressionKind.NotEquals: return _commandTree.CreateNotEqualsExpression(left, right); case DbExpressionKind.LessThan: return _commandTree.CreateLessThanExpression(left, right); case DbExpressionKind.GreaterThan: return _commandTree.CreateGreaterThanExpression(left, right); case DbExpressionKind.LessThanOrEquals: return _commandTree.CreateLessThanOrEqualsExpression(left, right); case DbExpressionKind.GreaterThanOrEquals: return _commandTree.CreateGreaterThanOrEqualsExpression(left, right); default: return null; } } public override DbExpression Visit(DbLikeExpression e) { return this._commandTree.CreateLikeExpression( VisitExpr(e.Argument), VisitExpr(e.Pattern), VisitExpr(e.Escape) ); } public override DbExpression Visit(DbLimitExpression e) { DbExpression argument = VisitExpr(e.Argument); DbExpression limit = VisitExpr(e.Limit); if (e.WithTies) { return _commandTree.CreateLimitWithTiesExpression(argument, limit); } else { return _commandTree.CreateLimitExpression(argument, limit); } } public override DbExpression Visit(DbIsNullExpression e) { DbExpression operand = this.VisitExpr(e.Argument); return this._commandTree.CreateIsNullExpression(operand); } public override DbExpression Visit(DbArithmeticExpression e) { List args = VisitExprList(e.Arguments); switch(e.ExpressionKind) { case DbExpressionKind.Plus: return _commandTree.CreatePlusExpression(args[0], args[1]); case DbExpressionKind.Minus: return _commandTree.CreateMinusExpression(args[0], args[1]); case DbExpressionKind.Multiply: return _commandTree.CreateMultiplyExpression(args[0], args[1]); case DbExpressionKind.Divide: return _commandTree.CreateDivideExpression(args[0], args[1]); case DbExpressionKind.Modulo: return _commandTree.CreateModuloExpression(args[0], args[1]); case DbExpressionKind.UnaryMinus: return _commandTree.CreateUnaryMinusExpression(args[0]); default: return null; } } public override DbExpression Visit(DbAndExpression e) { return _commandTree.CreateAndExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbOrExpression e) { return _commandTree.CreateOrExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbNotExpression e) { return _commandTree.CreateNotExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbDistinctExpression e) { return _commandTree.CreateDistinctExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbElementExpression e) { DbExpression arg = VisitExpr(e.Argument); if (e.IsSinglePropertyUnwrapped) { return _commandTree.CreateElementExpressionUnwrapSingleProperty(arg); } return _commandTree.CreateElementExpression(arg); } public override DbExpression Visit(DbIsEmptyExpression e) { return _commandTree.CreateIsEmptyExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbUnionAllExpression e) { return _commandTree.CreateUnionAllExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbIntersectExpression e) { return _commandTree.CreateIntersectExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbExceptExpression e) { return _commandTree.CreateExceptExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbTreatExpression e) { return _commandTree.CreateTreatExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbCastExpression e) { return _commandTree.CreateCastExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbIsOfExpression e) { if (DbExpressionKind.IsOfOnly == e.ExpressionKind) { return _commandTree.CreateIsOfOnlyExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); } else { return _commandTree.CreateIsOfExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); } } public override DbExpression Visit(DbOfTypeExpression e) { DbExpression arg = VisitExpr(e.Argument); TypeUsage ofType = _mapper.Map(e.OfType); if (DbExpressionKind.OfTypeOnly == e.ExpressionKind) { return _commandTree.CreateOfTypeOnlyExpression(arg, ofType); } else { return _commandTree.CreateOfTypeExpression(arg, ofType); } } public override DbExpression Visit(DbCaseExpression e) { return _commandTree.CreateCaseExpression(VisitExprList(e.When), VisitExprList(e.Then), VisitExpr(e.Else)); } public override DbExpression Visit(DbNewInstanceExpression e) { TypeUsage resultType = _mapper.Map(e.ResultType); List args = VisitExprList(e.Arguments); if (resultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType && e.HasRelatedEntityReferences) { List relatedRefs = new List (e.RelatedEntityReferences.Count); for(int idx = 0; idx < e.RelatedEntityReferences.Count; idx++) { DbRelatedEntityRef sourceRef = e.RelatedEntityReferences[idx]; RelationshipEndMember fromEnd = _mapper.Map(sourceRef.SourceEnd) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'source' relation end property using ExpressionCopier's metadata mapper"); RelationshipEndMember toEnd = _mapper.Map(sourceRef.TargetEnd) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'target' relation end property using ExpressionCopier's metadata mapper"); DbExpression targetRef = this.VisitExpr(sourceRef.TargetEntityReference); relatedRefs.Add(_commandTree.CreateRelatedEntityRef(fromEnd, toEnd, targetRef)); } return _commandTree.CreateNewEntityWithRelationshipsExpression((EntityType)resultType.EdmType, args, relatedRefs); } else { return _commandTree.CreateNewInstanceExpression(resultType, args); } } public override DbExpression Visit(DbRefExpression e) { RefType refType = TypeHelpers.GetEdmType (e.ResultType); EntityTypeBase targetType = refType.ElementType; return _commandTree.CreateRefExpression(_mapper.Map(e.EntitySet), VisitExpr(e.Argument), (EntityType)_mapper.Map(targetType)); } public override DbExpression Visit(DbRelationshipNavigationExpression e) { RelationshipEndMember fromEnd = _mapper.Map(e.NavigateFrom) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'from' relation end property using ExpressionCopier's metadata mapper"); RelationshipEndMember toEnd = _mapper.Map(e.NavigateTo) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'to' relation end property using ExpressionCopier's metadata mapper"); return _commandTree.CreateRelationshipNavigationExpression(fromEnd, toEnd, VisitExpr(e.NavigationSource)); } public override DbExpression Visit(DbDerefExpression e) { return _commandTree.CreateDerefExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbRefKeyExpression e) { return _commandTree.CreateRefKeyExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbEntityRefExpression e) { return _commandTree.CreateEntityRefExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbScanExpression e) { return _commandTree.CreateScanExpression(_mapper.Map(e.Target)); } public override DbExpression Visit(DbFilterExpression e) { return _commandTree.CreateFilterExpression(VisitBinding(e.Input), VisitExpr(e.Predicate)); } public override DbExpression Visit(DbProjectExpression e) { return _commandTree.CreateProjectExpression(VisitBinding(e.Input), VisitExpr(e.Projection)); } public override DbExpression Visit(DbCrossJoinExpression e) { return _commandTree.CreateCrossJoinExpression(VisitBindingList(e.Inputs)); } public override DbExpression Visit(DbJoinExpression e) { return _commandTree.CreateJoinExpressionByKind( e.ExpressionKind, VisitExpr(e.JoinCondition), VisitBinding(e.Left), VisitBinding(e.Right) ); } public override DbExpression Visit(DbApplyExpression e) { return _commandTree.CreateApplyExpressionByKind ( e.ExpressionKind, VisitBinding(e.Input), VisitBinding(e.Apply) ); } public override DbExpression Visit(DbGroupByExpression e) { List > keys = new List >(); List > aggs = new List >(); Debug.Assert(TypeSemantics.IsCollectionType(e.ResultType), "ExpressionCopier encountered DbGroupByExpression with non-collection result type"); CollectionType resultType = TypeHelpers.GetEdmType (_mapper.Map(e.ResultType)); Debug.Assert(TypeSemantics.IsRowType(resultType.TypeUsage), "ExpressionCopier encountered DbGroupByExpression with non-record result element type"); RowType resultElementType = TypeHelpers.GetEdmType (resultType.TypeUsage); ReadOnlyMetadataCollection cols = resultElementType.Properties; int iColPos = 0; for(int idx = 0; idx < e.Keys.Count; idx++) { keys.Add(new KeyValuePair (cols[iColPos].Name, VisitExpr(e.Keys[idx]))); iColPos++; } for(int idx = 0; idx < e.Aggregates.Count; idx++) { aggs.Add(new KeyValuePair (cols[iColPos].Name, VisitAggregate(e.Aggregates[idx]))); iColPos++; } return _commandTree.CreateGroupByExpression ( this.VisitGroupExpressionBinding(e.Input), keys, aggs ); } public override DbExpression Visit(DbSkipExpression e) { return _commandTree.CreateSkipExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder), VisitExpr(e.Count)); } public override DbExpression Visit(DbSortExpression e) { return _commandTree.CreateSortExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder)); } public override DbExpression Visit(DbQuantifierExpression e) { DbExpressionBinding eb = VisitBinding(e.Input); DbExpression pred = VisitExpr(e.Predicate); if (e.ExpressionKind == DbExpressionKind.Any) { return _commandTree.CreateAnyExpression(eb, pred); } else { return _commandTree.CreateAllExpression(eb, pred); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....], [....] //--------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Data.Common; using System.Data.Metadata.Edm; using System.Data.Common.CommandTrees; namespace System.Data.Common.CommandTrees.Internal { ////// Clones an expression tree /// internal class ExpressionCopier : DbExpressionVisitor{ /// /// The MetadataMapper class is a helper class that logically translates /// metadata constructs from one space to another. The objects that are translated /// include /// Types /// Properties /// Methods /// Functions /// Extents /// EntitySets /// The default implementation is to simply return the specified metadata instance /// (an 'identity' mapping) /// protected class MetadataMapper { internal static readonly MetadataMapper IdentityMapper = new MetadataMapper(); internal MetadataMapper() {} internal virtual EdmType Map(EdmType s) { return s; } internal virtual EntitySetBase Map(EntitySetBase e) { return e; } internal virtual EntitySet Map(EntitySet e) { return e; } internal virtual EdmFunction Map(EdmFunction f) { return f; } internal virtual NavigationProperty Map(NavigationProperty p) { return p; } internal virtual EdmProperty Map(EdmProperty p) { return p; } internal virtual RelationshipEndMember Map(RelationshipEndMember m) { return m; } internal virtual TypeUsage Map(TypeUsage t) { return t; } #if METHOD_EXPRESSION internal virtual MethodMetadata Map(MethodMetadata m) { return m; } #endif } private class WorkspaceMapper : MetadataMapper { private MetadataWorkspace _metadata; private Dictionary_transientTypes = new Dictionary (); internal WorkspaceMapper(MetadataWorkspace destinationWorkspace) : base() { _metadata = destinationWorkspace; } #region MetadataMapper Overrides internal override EdmType Map(EdmType type) { EdmType retType = null; if (BuiltInTypeKind.RefType == type.BuiltInTypeKind) { RefType refType = (RefType)type; retType = new RefType((EntityType)Map(refType.ElementType)); } else if (BuiltInTypeKind.CollectionType == type.BuiltInTypeKind) { CollectionType collectionType = (CollectionType)type; retType = new CollectionType(Map(collectionType.TypeUsage)); } else if (BuiltInTypeKind.RowType == type.BuiltInTypeKind) { RowType rowType = (RowType)type; List columns = new List (); foreach (EdmProperty p in rowType.Properties) { columns.Add(new EdmProperty(p.Name, Map(p.TypeUsage))); } RowType newRowType = new RowType(columns, rowType.InitializerMetadata); retType = newRowType; } else { if (!_metadata.TryGetType(type.Name, type.NamespaceName, type.DataSpace, out retType) || null == retType) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_TypeNotFound(TypeHelpers.GetFullName(type))); } } return retType; } internal override EntitySetBase Map(EntitySetBase e) { EntityContainer container; if (_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container)) { EntitySetBase extent = null; if (container.BaseEntitySets.TryGetValue(e.Name, false, out extent) && extent != null) { return extent; } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name)); } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name)); } internal override EntitySet Map(EntitySet e) { EntityContainer container; if(_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container)) { EntitySetBase set = null; if (container.BaseEntitySets.TryGetValue(e.Name, false, out set)) { EntitySet entitySet = set as EntitySet; if (entitySet != null) { return entitySet; } } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name)); } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name)); } internal override EdmFunction Map(EdmFunction f) { TypeUsage[] paramTypes = new TypeUsage[f.Parameters.Count]; int idx = 0; foreach (FunctionParameter p in f.Parameters) { paramTypes[idx] = Map(p.TypeUsage); idx++; } EdmFunction retFunc = null; if( _metadata.TryGetFunction(f.Name, f.NamespaceName, paramTypes, false, f.DataSpace, out retFunc) && retFunc != null) { return retFunc; } throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_FunctionNotFound(TypeHelpers.GetFullName(f))); } internal override NavigationProperty Map(NavigationProperty prop) { NavigationProperty retProp; if (!TryMapMember(prop, out retProp)) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType))); } return retProp; } internal override EdmProperty Map(EdmProperty prop) { EdmProperty retProp; if (!TryMapMember(prop, out retProp)) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType))); } return retProp; } internal override RelationshipEndMember Map(RelationshipEndMember end) { RelationshipEndMember retEnd; if (!TryMapMember(end, out retEnd)) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EndNotFound(end.Name, TypeHelpers.GetFullName(end.DeclaringType))); } return retEnd; } private bool TryMapMember (TMemberType prop, out TMemberType foundProp) where TMemberType : EdmMember { foundProp = null; StructuralType mappedType = Map(prop.DeclaringType) as StructuralType; if (mappedType != null) { EdmMember foundMember = null; if (mappedType.Members.TryGetValue(prop.Name, false, out foundMember)) { foundProp = foundMember as TMemberType; } } return (foundProp != null); } #if METHOD_EXPRESSION internal override MethodMetadata Map(MethodMetadata meth) { MethodMetadata retMethod = null; List mappedParamTypes = new List (); foreach (IParameterMetadata methParam in meth.Parameters) { mappedParamTypes.Add(this.Map(methParam.Type)); } TypeMetadata mappedType = this.Map(meth.DefiningType); foreach (MemberMetadata member in mappedType.GetMemberByName(meth.Name)) { // Ignore the member if: // - It's not a method, OR // - It's IsStatic property doesn't match, OR // - It doesn't declare the right number of parameters. MethodMetadata mappedMeth = member as MethodMetadata; if( null == mappedMeth || mappedMeth.IsStatic != meth.IsStatic || mappedMeth.Parameters.Count != mappedParamTypes.Count) { continue; } // Assume that the method matches, which is correct for the case // where the required method and this method both declare no parameters. bool paramMatch = true; for (int idx = 0; idx < mappedParamTypes.Count; idx++) { // If the type of any parameter to the method under consideration // does not match the type of the corresponding parameter from the // source method, then this cannot be the correct destination method. if (!mappedParamTypes[idx].Equals(mappedMeth.Parameters[idx].Type)) { paramMatch = false; break; } } // If any of the parameter types didn't match then move on. if (!paramMatch) { continue; } // This is the required method. retMethod = mappedMeth; break; } if (null == retMethod) { throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_MethodNotFound(meth.Name, mappedType.FullName)); } return retMethod; } #endif internal override TypeUsage Map(TypeUsage type) { // // If the target metatadata workspace contains the same type instances, then the type does not // need to be 'mapped' and the same TypeUsage instance may be returned. This can happen if the // target workspace and the workspace of the source Command Tree are using the same ItemCollection. // EdmType retEdmType = Map(type.EdmType); if (object.ReferenceEquals(retEdmType, type.EdmType)) { return type; } // // Retrieve the Facets from this type usage so that // 1) They can be used to map the type if it is a primitive type // 2) They can be applied to the new type usage that references the mapped type // Facet[] facets = new Facet[type.Facets.Count]; int idx = 0; foreach (Facet f in type.Facets) { facets[idx] = f; idx++; } return TypeUsage.Create(retEdmType, facets); } #endregion } private MetadataMapper _mapper; private DbCommandTree _commandTree; protected DbCommandTree CommandTree { get { return this._commandTree; } } protected ExpressionCopier(DbCommandTree commandTree, MetadataMapper mapper) { _commandTree = commandTree; _mapper = mapper; } private static MetadataMapper GetMapper(MetadataWorkspace source, MetadataWorkspace destination) { ItemCollection mappingItemCollection = source.GetItemCollection(DataSpace.CSSpace); ItemCollection destinationMappingItemCollection = destination.GetItemCollection(DataSpace.CSSpace); if (!object.ReferenceEquals(mappingItemCollection, destinationMappingItemCollection)) { EntityBid.Trace(" Using cross-workspace metadata mapper\n"); return new WorkspaceMapper(destination); } EntityBid.Trace(" Using identity metadata mapper\n"); return MetadataMapper.IdentityMapper; } internal static DbExpression Copy(DbCommandTree destination, DbExpression expression) { Debug.Assert(destination != null, "Destination Command Tree is null"); Debug.Assert(expression != null, "DbExpression is null"); using(new EntityBid.ScopeAuto(" destination=%d#", destination.ObjectId)) { EntityBid.Trace(" expression=%d#, %d{cqt.DbExpressionKind}\n", DbExpression.GetObjectId(expression), DbExpression.GetExpressionKind(expression)); ExpressionCopier copier = new ExpressionCopier(destination, GetMapper(expression.CommandTree.MetadataWorkspace, destination.MetadataWorkspace)); return copier.VisitExpr(expression); } } public List VisitList (IList exprList) where T: DbExpression { List retList = null; if (exprList != null) { retList = new List (); for (int idx = 0; idx < exprList.Count; idx++) { retList.Add((T)this.VisitExpr(exprList[idx])); } } return retList; } public List VisitExprList(IList exprList) { return VisitList (exprList); } public DbExpressionBinding VisitBinding(DbExpressionBinding b) { DbExpression newExpr = VisitExpr(b.Expression); return this._commandTree.CreateExpressionBinding(newExpr, b.VariableName); } public DbGroupExpressionBinding VisitGroupExpressionBinding(DbGroupExpressionBinding gb) { DbExpression newExpr = VisitExpr(gb.Expression); return this._commandTree.CreateGroupExpressionBinding(newExpr, gb.VariableName, gb.GroupVariableName); } public List VisitBindingList(IList bindingList) { List retList = null; if (bindingList != null) { retList = new List (); for (int idx = 0; idx < bindingList.Count; idx++) { retList.Add(this.VisitBinding(bindingList[idx])); } } return retList; } public List VisitSortOrder(IList sortOrder) { List skeys = new List (); for(int idx = 0; idx < sortOrder.Count; idx++) { DbSortClause s = sortOrder[idx]; DbExpression keyExpr = VisitExpr(s.Expression); bool asc = s.Ascending; if(!string.IsNullOrEmpty(s.Collation)) { skeys.Add(_commandTree.CreateSortClause(keyExpr, asc, s.Collation)); } else { skeys.Add(_commandTree.CreateSortClause(keyExpr, asc)); } } return skeys; } public virtual DbFunctionAggregate VisitFunctionAggregate(DbFunctionAggregate a) { if (a.Distinct) { return _commandTree.CreateDistinctFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0])); } else { return _commandTree.CreateFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0])); } } #if ENABLE_NESTAGGREGATE public virtual NestAggregate VisitNestAggregate(NestAggregate a) { return _commandTree.CreateNestAggregate(VisitExpr(a.Arguments[0])); } #endif public DbAggregate VisitAggregate(DbAggregate a) { DbFunctionAggregate funcA = a as DbFunctionAggregate; if (funcA != null) { return VisitFunctionAggregate(funcA); } #if ENABLE_NESTAGGREGATE else if (a is NestAggregate) { return VisitNestAggregate(a as NestAggregate); } #endif return null; } public DbExpression VisitExpr(DbExpression expr) { if (expr == null) { return null; } return expr.Accept (this); } #region DbExpressionVisitor Members public override DbExpression Visit(DbExpression e) { throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_General_UnsupportedExpression(e.GetType().FullName)); } public override DbExpression Visit(DbConstantExpression e) { return _commandTree.CreateConstantExpression(e.Value, _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbNullExpression e) { return _commandTree.CreateNullExpression(_mapper.Map(e.ResultType)); } public override DbExpression Visit(DbVariableReferenceExpression e) { return _commandTree.CreateVariableReferenceExpression(e.VariableName, _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbParameterReferenceExpression e) { return _commandTree.CreateParameterReferenceExpression(e.ParameterName); } public override DbExpression Visit(DbFunctionExpression e) { if (e.IsLambda) { List > formals = new List >(); for(int idx = 0; idx < e.Function.Parameters.Count; idx++) { FunctionParameter formal = e.Function.Parameters[idx]; formals.Add(new KeyValuePair (formal.Name, _mapper.Map(formal.TypeUsage))); } return _commandTree.CreateLambdaFunctionExpression(formals, VisitExpr(e.LambdaBody), VisitExprList(e.Arguments)); } else { return _commandTree.CreateFunctionExpression(_mapper.Map(e.Function), VisitExprList(e.Arguments)); } } #if METHOD_EXPRESSION public override Expression Visit(MethodExpression e) { if (e.Method.IsStatic) { return _commandTree.CreateStaticMethodExpression(_mapper.Map(e.Method), VisitExprList(e.Arguments)); } else { return _commandTree.CreateInstanceMethodExpression(_mapper.Map(e.Method), VisitExpr(e.Instance), VisitExprList(e.Arguments)); } } #endif public override DbExpression Visit(DbPropertyExpression e) { DbExpression instanceCopy = VisitExpr(e.Instance); if (Helper.IsNavigationProperty(e.Property)) { return _commandTree.CreatePropertyExpression(_mapper.Map((NavigationProperty)e.Property), instanceCopy); } else if (Helper.IsEdmProperty(e.Property)) { return _commandTree.CreatePropertyExpression(_mapper.Map((EdmProperty)e.Property), instanceCopy); } else { Debug.Assert(e.Property is RelationshipEndMember, "Invalid DbPropertyExpression - Property is not EdmProperty, NavigationProperty or RelationshipEndMember"); return _commandTree.CreatePropertyExpression(_mapper.Map((RelationshipEndMember)e.Property), instanceCopy); } } public override DbExpression Visit(DbComparisonExpression e) { DbExpression left = VisitExpr(e.Left); DbExpression right = VisitExpr(e.Right); switch (e.ExpressionKind) { case DbExpressionKind.Equals: return _commandTree.CreateEqualsExpression(left, right); case DbExpressionKind.NotEquals: return _commandTree.CreateNotEqualsExpression(left, right); case DbExpressionKind.LessThan: return _commandTree.CreateLessThanExpression(left, right); case DbExpressionKind.GreaterThan: return _commandTree.CreateGreaterThanExpression(left, right); case DbExpressionKind.LessThanOrEquals: return _commandTree.CreateLessThanOrEqualsExpression(left, right); case DbExpressionKind.GreaterThanOrEquals: return _commandTree.CreateGreaterThanOrEqualsExpression(left, right); default: return null; } } public override DbExpression Visit(DbLikeExpression e) { return this._commandTree.CreateLikeExpression( VisitExpr(e.Argument), VisitExpr(e.Pattern), VisitExpr(e.Escape) ); } public override DbExpression Visit(DbLimitExpression e) { DbExpression argument = VisitExpr(e.Argument); DbExpression limit = VisitExpr(e.Limit); if (e.WithTies) { return _commandTree.CreateLimitWithTiesExpression(argument, limit); } else { return _commandTree.CreateLimitExpression(argument, limit); } } public override DbExpression Visit(DbIsNullExpression e) { DbExpression operand = this.VisitExpr(e.Argument); return this._commandTree.CreateIsNullExpression(operand); } public override DbExpression Visit(DbArithmeticExpression e) { List args = VisitExprList(e.Arguments); switch(e.ExpressionKind) { case DbExpressionKind.Plus: return _commandTree.CreatePlusExpression(args[0], args[1]); case DbExpressionKind.Minus: return _commandTree.CreateMinusExpression(args[0], args[1]); case DbExpressionKind.Multiply: return _commandTree.CreateMultiplyExpression(args[0], args[1]); case DbExpressionKind.Divide: return _commandTree.CreateDivideExpression(args[0], args[1]); case DbExpressionKind.Modulo: return _commandTree.CreateModuloExpression(args[0], args[1]); case DbExpressionKind.UnaryMinus: return _commandTree.CreateUnaryMinusExpression(args[0]); default: return null; } } public override DbExpression Visit(DbAndExpression e) { return _commandTree.CreateAndExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbOrExpression e) { return _commandTree.CreateOrExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbNotExpression e) { return _commandTree.CreateNotExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbDistinctExpression e) { return _commandTree.CreateDistinctExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbElementExpression e) { DbExpression arg = VisitExpr(e.Argument); if (e.IsSinglePropertyUnwrapped) { return _commandTree.CreateElementExpressionUnwrapSingleProperty(arg); } return _commandTree.CreateElementExpression(arg); } public override DbExpression Visit(DbIsEmptyExpression e) { return _commandTree.CreateIsEmptyExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbUnionAllExpression e) { return _commandTree.CreateUnionAllExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbIntersectExpression e) { return _commandTree.CreateIntersectExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbExceptExpression e) { return _commandTree.CreateExceptExpression(VisitExpr(e.Left), VisitExpr(e.Right)); } public override DbExpression Visit(DbTreatExpression e) { return _commandTree.CreateTreatExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbCastExpression e) { return _commandTree.CreateCastExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType)); } public override DbExpression Visit(DbIsOfExpression e) { if (DbExpressionKind.IsOfOnly == e.ExpressionKind) { return _commandTree.CreateIsOfOnlyExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); } else { return _commandTree.CreateIsOfExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); } } public override DbExpression Visit(DbOfTypeExpression e) { DbExpression arg = VisitExpr(e.Argument); TypeUsage ofType = _mapper.Map(e.OfType); if (DbExpressionKind.OfTypeOnly == e.ExpressionKind) { return _commandTree.CreateOfTypeOnlyExpression(arg, ofType); } else { return _commandTree.CreateOfTypeExpression(arg, ofType); } } public override DbExpression Visit(DbCaseExpression e) { return _commandTree.CreateCaseExpression(VisitExprList(e.When), VisitExprList(e.Then), VisitExpr(e.Else)); } public override DbExpression Visit(DbNewInstanceExpression e) { TypeUsage resultType = _mapper.Map(e.ResultType); List args = VisitExprList(e.Arguments); if (resultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType && e.HasRelatedEntityReferences) { List relatedRefs = new List (e.RelatedEntityReferences.Count); for(int idx = 0; idx < e.RelatedEntityReferences.Count; idx++) { DbRelatedEntityRef sourceRef = e.RelatedEntityReferences[idx]; RelationshipEndMember fromEnd = _mapper.Map(sourceRef.SourceEnd) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'source' relation end property using ExpressionCopier's metadata mapper"); RelationshipEndMember toEnd = _mapper.Map(sourceRef.TargetEnd) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'target' relation end property using ExpressionCopier's metadata mapper"); DbExpression targetRef = this.VisitExpr(sourceRef.TargetEntityReference); relatedRefs.Add(_commandTree.CreateRelatedEntityRef(fromEnd, toEnd, targetRef)); } return _commandTree.CreateNewEntityWithRelationshipsExpression((EntityType)resultType.EdmType, args, relatedRefs); } else { return _commandTree.CreateNewInstanceExpression(resultType, args); } } public override DbExpression Visit(DbRefExpression e) { RefType refType = TypeHelpers.GetEdmType (e.ResultType); EntityTypeBase targetType = refType.ElementType; return _commandTree.CreateRefExpression(_mapper.Map(e.EntitySet), VisitExpr(e.Argument), (EntityType)_mapper.Map(targetType)); } public override DbExpression Visit(DbRelationshipNavigationExpression e) { RelationshipEndMember fromEnd = _mapper.Map(e.NavigateFrom) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'from' relation end property using ExpressionCopier's metadata mapper"); RelationshipEndMember toEnd = _mapper.Map(e.NavigateTo) as RelationshipEndMember; Debug.Assert(fromEnd != null, "Unable to map 'to' relation end property using ExpressionCopier's metadata mapper"); return _commandTree.CreateRelationshipNavigationExpression(fromEnd, toEnd, VisitExpr(e.NavigationSource)); } public override DbExpression Visit(DbDerefExpression e) { return _commandTree.CreateDerefExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbRefKeyExpression e) { return _commandTree.CreateRefKeyExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbEntityRefExpression e) { return _commandTree.CreateEntityRefExpression(VisitExpr(e.Argument)); } public override DbExpression Visit(DbScanExpression e) { return _commandTree.CreateScanExpression(_mapper.Map(e.Target)); } public override DbExpression Visit(DbFilterExpression e) { return _commandTree.CreateFilterExpression(VisitBinding(e.Input), VisitExpr(e.Predicate)); } public override DbExpression Visit(DbProjectExpression e) { return _commandTree.CreateProjectExpression(VisitBinding(e.Input), VisitExpr(e.Projection)); } public override DbExpression Visit(DbCrossJoinExpression e) { return _commandTree.CreateCrossJoinExpression(VisitBindingList(e.Inputs)); } public override DbExpression Visit(DbJoinExpression e) { return _commandTree.CreateJoinExpressionByKind( e.ExpressionKind, VisitExpr(e.JoinCondition), VisitBinding(e.Left), VisitBinding(e.Right) ); } public override DbExpression Visit(DbApplyExpression e) { return _commandTree.CreateApplyExpressionByKind ( e.ExpressionKind, VisitBinding(e.Input), VisitBinding(e.Apply) ); } public override DbExpression Visit(DbGroupByExpression e) { List > keys = new List >(); List > aggs = new List >(); Debug.Assert(TypeSemantics.IsCollectionType(e.ResultType), "ExpressionCopier encountered DbGroupByExpression with non-collection result type"); CollectionType resultType = TypeHelpers.GetEdmType (_mapper.Map(e.ResultType)); Debug.Assert(TypeSemantics.IsRowType(resultType.TypeUsage), "ExpressionCopier encountered DbGroupByExpression with non-record result element type"); RowType resultElementType = TypeHelpers.GetEdmType (resultType.TypeUsage); ReadOnlyMetadataCollection cols = resultElementType.Properties; int iColPos = 0; for(int idx = 0; idx < e.Keys.Count; idx++) { keys.Add(new KeyValuePair (cols[iColPos].Name, VisitExpr(e.Keys[idx]))); iColPos++; } for(int idx = 0; idx < e.Aggregates.Count; idx++) { aggs.Add(new KeyValuePair (cols[iColPos].Name, VisitAggregate(e.Aggregates[idx]))); iColPos++; } return _commandTree.CreateGroupByExpression ( this.VisitGroupExpressionBinding(e.Input), keys, aggs ); } public override DbExpression Visit(DbSkipExpression e) { return _commandTree.CreateSkipExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder), VisitExpr(e.Count)); } public override DbExpression Visit(DbSortExpression e) { return _commandTree.CreateSortExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder)); } public override DbExpression Visit(DbQuantifierExpression e) { DbExpressionBinding eb = VisitBinding(e.Input); DbExpression pred = VisitExpr(e.Predicate); if (e.ExpressionKind == DbExpressionKind.Any) { return _commandTree.CreateAnyExpression(eb, pred); } else { return _commandTree.CreateAllExpression(eb, pred); } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SmtpCommands.cs
- BindingNavigator.cs
- EntityDataSourceQueryBuilder.cs
- HtmlElementErrorEventArgs.cs
- WeakReference.cs
- sqlpipe.cs
- FontFamilyIdentifier.cs
- CredentialSelector.cs
- AssemblyName.cs
- IsolatedStorageException.cs
- DropDownList.cs
- PrintDialogException.cs
- LicFileLicenseProvider.cs
- _DomainName.cs
- FixedTextSelectionProcessor.cs
- OdbcErrorCollection.cs
- SoapSchemaExporter.cs
- DictionaryGlobals.cs
- DetailsViewPagerRow.cs
- LabelAutomationPeer.cs
- util.cs
- WebPartsPersonalization.cs
- EntityTransaction.cs
- BamlMapTable.cs
- IndentedWriter.cs
- EntityDataSourceEntityTypeFilterConverter.cs
- RequestCacheValidator.cs
- XmlConvert.cs
- AstNode.cs
- EnlistmentTraceIdentifier.cs
- AnimatedTypeHelpers.cs
- ThreadInterruptedException.cs
- NamedPipeTransportManager.cs
- BamlResourceContent.cs
- WebConfigurationHostFileChange.cs
- NTAccount.cs
- MessageQueueKey.cs
- PersonalizationProvider.cs
- DataSourceCache.cs
- FactoryId.cs
- DataSetMappper.cs
- ReliableChannelFactory.cs
- CompiledQueryCacheEntry.cs
- ThicknessKeyFrameCollection.cs
- CurrentChangingEventManager.cs
- OleDbRowUpdatingEvent.cs
- DataGridTextColumn.cs
- RefreshEventArgs.cs
- ReachObjectContext.cs
- PreDigestedSignedInfo.cs
- SynchronizationContext.cs
- DependencyPropertyChangedEventArgs.cs
- ObjectDataSourceEventArgs.cs
- ModelPerspective.cs
- ExtendedPropertyCollection.cs
- CodeAccessPermission.cs
- TextBox.cs
- StateBag.cs
- AsymmetricSignatureDeformatter.cs
- HttpRequestWrapper.cs
- Camera.cs
- TraceData.cs
- VisemeEventArgs.cs
- ApplicationDirectory.cs
- DefaultAsyncDataDispatcher.cs
- RuleConditionDialog.Designer.cs
- GuidelineCollection.cs
- DesignerValidatorAdapter.cs
- InternalDispatchObject.cs
- DynamicDiscoveryDocument.cs
- XmlSerializerVersionAttribute.cs
- ExecutedRoutedEventArgs.cs
- MediaPlayer.cs
- ColorComboBox.cs
- WsatServiceCertificate.cs
- ObjectDataProvider.cs
- SymDocumentType.cs
- StretchValidation.cs
- Int32CollectionValueSerializer.cs
- ListViewInsertEventArgs.cs
- StaticDataManager.cs
- SQLInt32Storage.cs
- DynamicValueConverter.cs
- StructuredTypeEmitter.cs
- DrawingContextWalker.cs
- PackageStore.cs
- DbgCompiler.cs
- FunctionCommandText.cs
- QilDataSource.cs
- DataGridViewSelectedRowCollection.cs
- ListViewDataItem.cs
- PackUriHelper.cs
- ToolboxComponentsCreatedEventArgs.cs
- DataGridRelationshipRow.cs
- BaseParagraph.cs
- FileVersionInfo.cs
- Util.cs
- TextReader.cs
- XmlnsDefinitionAttribute.cs
- LockedHandleGlyph.cs