コード例 #1
0
        /// <summary>
        /// Creates a ProviderCommandInfo for the given node.
        /// This method should be called when the keys, foreign keys and sort keys are known ahead of time.
        /// Typically it is used when the original command is factored into multiple commands.
        /// </summary>
        /// <param name="command">The owning command, used for creating VarVecs, etc</param>
        /// <param name="node">The root of the sub-command for which a ProviderCommandInfo should be generated</param>
        /// <param name="children">A list of ProviderCommandInfos that were created for the child sub-commands.</param>
        /// <returns>The resulting ProviderCommandInfo</returns>
        internal static ProviderCommandInfo Create(
            Command command,
            Node node,
            List <ProviderCommandInfo> children)
        {
            PhysicalProjectOp projectOp = node.Op as PhysicalProjectOp;

            PlanCompiler.Assert(projectOp != null, "Expected root Op to be a physical Project");

            // build up the CQT
            DbCommandTree      ctree  = CTreeGenerator.Generate(command, node);
            DbQueryCommandTree cqtree = ctree as DbQueryCommandTree;

            PlanCompiler.Assert(cqtree != null, "null query command tree");

            // Get the rowtype for the result cqt
            md.CollectionType collType = TypeHelpers.GetEdmType <md.CollectionType>(cqtree.Query.ResultType);
            PlanCompiler.Assert(md.TypeSemantics.IsRowType(collType.TypeUsage), "command rowtype is not a record");

            // Build up a mapping from Vars to the corresponding output property/column
            Dictionary <Var, md.EdmProperty> outputVarMap = BuildOutputVarMap(projectOp, collType.TypeUsage);

            return(new ProviderCommandInfo(ctree, children));
        }
コード例 #2
0
        private static bool TryGetCommonType(CollectionType collectionType1, CollectionType collectionType2, out EdmType commonType)
        {
            TypeUsage commonTypeUsage = null;
            if (!TryGetCommonType(collectionType1.TypeUsage, collectionType2.TypeUsage, out commonTypeUsage))
            {
                commonType = null;
                return false;
            }

            commonType = new CollectionType(commonTypeUsage);
            return true;
        }
コード例 #3
0
        private DbExpression RewriteCollection(DbExpression expression, CollectionType collectionType)
        {
            DbExpression target = expression;

            // If the collection expression is a project expression, get a strongly typed reference to it for later use.
            DbProjectExpression project = null;
            if (DbExpressionKind.Project == expression.ExpressionKind)
            {
                project = (DbProjectExpression)expression;
                target = project.Input.Expression;
            }

            // If Relationship span is enabled and the source of this collection is (directly or indirectly)
            // a RelationshipNavigation operation, it may be possible to optimize the relationship span rewrite
            // for the Entities produced by the navigation. 
            NavigationInfo navInfo = null;
            if (this.RelationshipSpan)
            {
                // Attempt to find a RelationshipNavigationExpression in the collection-defining expression
                target = RelationshipNavigationVisitor.FindNavigationExpression(target, _aliasGenerator, out navInfo);
            }

            // If a relationship navigation expression defines this collection, make the Ref that is the navigation source
            // and the source association end available for possible use when the projection over the collection is rewritten.
            if (navInfo != null)
            {
                this.EnterNavigationCollection(navInfo);
            }
            else
            {
                // Otherwise, add a null navigation info instance to the stack to indicate that relationship navigation
                // cannot be optimized for the entities produced by this collection expression (if it is a collection of entities).
                this.EnterCollection();
            }
            
            // If the expression is already a DbProjectExpression then simply visit the projection,
            // instead of introducing another projection over the existing one.
            DbExpression result = expression;
            if (project != null)
            {
                DbExpression newProjection = this.Rewrite(project.Projection);
                if (!object.ReferenceEquals(project.Projection, newProjection))
                {
                    result = target.BindAs(project.Input.VariableName).Project(newProjection);
                }
            }
            else
            {
                // This is not a recognized special case, so simply add the span projection over the original
                // collection-producing expression, if it is required.
                DbExpressionBinding collectionBinding = target.BindAs(_aliasGenerator.Next());
                DbExpression projection = collectionBinding.Variable;

                DbExpression spannedProjection = this.Rewrite(projection);

                if (!object.ReferenceEquals(projection, spannedProjection))
                {
                    result = collectionBinding.Project(spannedProjection);
                }
            }

            // Remove any navigation information from scope, if it was added
            this.ExitCollection();

            // If a navigation expression defines this collection and its navigation information was used to
            // short-circuit relationship span rewrites, then enclose the entire rewritten expression in a
            // Lambda binding that brings the source Ref of the navigation operation into scope. This ref is
            // refered to by VariableReferenceExpressions in the original navigation expression as well as any
            // short-circuited relationship span columns in the rewritten expression.
            if (navInfo != null && navInfo.InUse)
            {
                // Create a Lambda function that binds the original navigation source expression under the variable name
                // used in the navigation expression and the relationship span columns, and which has its Lambda body
                // defined by the rewritten collection expression.
                List<DbVariableReferenceExpression> formals = new List<DbVariableReferenceExpression>(1);
                formals.Add(navInfo.SourceVariable);

                List<DbExpression> args = new List<DbExpression>(1);
                args.Add(navInfo.Source);

                result = DbExpressionBuilder.Invoke(DbExpressionBuilder.Lambda(result, formals), args);
            }

            // Return the (possibly rewritten) collection expression.
            return result;
        }
コード例 #4
0
ファイル: TypeUsage.cs プロジェクト: dox0/DotNet471RS3
        /// <summary>
        /// Returns a Model type usage for a provider type
        /// </summary>
        /// <returns>model (CSpace) type usage</returns>
        internal TypeUsage GetModelTypeUsage()
        {
            if (_modelTypeUsage == null)
            {
                EdmType edmType = this.EdmType;

                // If the edm type is already a cspace type, return the same type
                if (edmType.DataSpace == DataSpace.CSpace || edmType.DataSpace == DataSpace.OSpace)
                {
                    return(this);
                }

                TypeUsage result;
                if (Helper.IsRowType(edmType))
                {
                    RowType       sspaceRowType = (RowType)edmType;
                    EdmProperty[] properties    = new EdmProperty[sspaceRowType.Properties.Count];
                    for (int i = 0; i < properties.Length; i++)
                    {
                        EdmProperty sspaceProperty = sspaceRowType.Properties[i];
                        TypeUsage   newTypeUsage   = sspaceProperty.TypeUsage.GetModelTypeUsage();
                        properties[i] = new EdmProperty(sspaceProperty.Name, newTypeUsage);
                    }
                    RowType edmRowType = new RowType(properties, sspaceRowType.InitializerMetadata);
                    result = TypeUsage.Create(edmRowType, this.Facets);
                }
                else if (Helper.IsCollectionType(edmType))
                {
                    CollectionType sspaceCollectionType = ((CollectionType)edmType);
                    TypeUsage      newTypeUsage         = sspaceCollectionType.TypeUsage.GetModelTypeUsage();
                    result = TypeUsage.Create(new CollectionType(newTypeUsage), this.Facets);
                }
                else if (Helper.IsRefType(edmType))
                {
                    System.Diagnostics.Debug.Assert(((RefType)edmType).ElementType.DataSpace == DataSpace.CSpace);
                    result = this;
                }
                else if (Helper.IsPrimitiveType(edmType))
                {
                    result = ((PrimitiveType)edmType).ProviderManifest.GetEdmType(this);

                    if (result == null)
                    {
                        throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Mapping_ProviderReturnsNullType(this.ToString()));
                    }

                    if (!TypeSemantics.IsNullable(this))
                    {
                        result = TypeUsage.Create(result.EdmType,
                                                  OverrideFacetValues(result.Facets,
                                                                      new FacetValues {
                            Nullable = false
                        }));
                    }
                }
                else if (Helper.IsEntityTypeBase(edmType) || Helper.IsComplexType(edmType))
                {
                    result = this;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false, "Unexpected type found in entity data reader");
                    return(null);
                }
                System.Threading.Interlocked.CompareExchange(ref _modelTypeUsage, result, null);
            }
            return(_modelTypeUsage);
        }
コード例 #5
0
        // Generates and caches a command definition for the given function
        internal DbCommandDefinition GenerateCommandDefinition(StorageModificationFunctionMapping functionMapping)
        {
            if (null == m_modificationFunctionCommandDefinitions) 
            { 
                m_modificationFunctionCommandDefinitions = new Dictionary<StorageModificationFunctionMapping,DbCommandDefinition>();
            }
            DbCommandDefinition commandDefinition;
            if (!m_modificationFunctionCommandDefinitions.TryGetValue(functionMapping, out commandDefinition))
            {
                // synthesize a RowType for this mapping
                TypeUsage resultType = null;
                if (null != functionMapping.ResultBindings && 0 < functionMapping.ResultBindings.Count)
                {
                    List<EdmProperty> properties = new List<EdmProperty>(functionMapping.ResultBindings.Count);
                    foreach (StorageModificationFunctionResultBinding resultBinding in functionMapping.ResultBindings)
                    {
                        properties.Add(new EdmProperty(resultBinding.ColumnName, resultBinding.Property.TypeUsage));
                    }
                    RowType rowType = new RowType(properties);
                    CollectionType collectionType = new CollectionType(rowType);
                    resultType = TypeUsage.Create(collectionType);
                }

                // add function parameters
                IEnumerable<KeyValuePair<string, TypeUsage>> functionParams =
                    functionMapping.Function.Parameters.Select(paramInfo => new KeyValuePair<string, TypeUsage>(paramInfo.Name, paramInfo.TypeUsage));
                
                // construct DbFunctionCommandTree including implict return type
                DbFunctionCommandTree tree = new DbFunctionCommandTree(m_metadataWorkspace, DataSpace.SSpace,
                    functionMapping.Function, resultType, functionParams);
                                
                commandDefinition = m_providerServices.CreateCommandDefinition(tree);
            }
            return commandDefinition;
        }
コード例 #6
0
        internal override TypeUsage GetTypeUsage()
        {
            if (_typeUsage != null)
            {
                return _typeUsage;
            }
            Debug.Assert(_typeSubElement != null, "For attributes typeusage should have been resolved");
            
            if (_typeSubElement != null)
            {
                CollectionType collectionType = new CollectionType(_typeSubElement.GetTypeUsage());

                collectionType.AddMetadataProperties(this.OtherContent);
                _typeUsage = TypeUsage.Create(collectionType);
            }
            return _typeUsage;
        }
コード例 #7
0
        protected override void Visit(CollectionType collectionType)
        {
            int index;
            if (!this.AddObjectToSeenListAndHashBuilder(collectionType, out index))
            {
                return;
            }

            this.AddObjectStartDumpToHashBuilder(collectionType, index);

            #region Inner data visit
            this.AddObjectContentToHashBuilder(collectionType.Identity);
            // Identity contains Name, NamespaceName and FullName

            base.Visit(collectionType);

            #endregion

            this.AddObjectEndDumpToHashBuilder();
        }
コード例 #8
0
 protected virtual void Visit(CollectionType collectionType)
 {
     Visit(collectionType.BaseType);
     Visit(collectionType.TypeUsage);
 }
コード例 #9
0
        /// <summary>Convert CSpace TypeMetadata into OSpace TypeMetadata</summary>
        /// <param name="clrType"></param>
        /// <returns>OSpace type metadata</returns>
        private EdmType ConvertOSpaceToCSpaceType(EdmType clrType)
        {
            EdmType cdmType = null;

            if (Helper.IsCollectionType(clrType))
            {
                EdmType elemType = ConvertOSpaceToCSpaceType(((CollectionType)clrType).TypeUsage.EdmType);
                cdmType = new CollectionType(elemType);
            }
            else if (Helper.IsRowType(clrType))
            {
                List<EdmProperty> cdmProperties = new List<EdmProperty>();
                foreach (EdmProperty column in ((RowType)clrType).Properties)
                {
                    EdmType cdmPropertyType = ConvertOSpaceToCSpaceType(column.TypeUsage.EdmType);
                    EdmProperty cdmPorperty = new EdmProperty(column.Name, TypeUsage.Create(cdmPropertyType));
                    cdmProperties.Add(cdmPorperty);
                }
                cdmType = new RowType(cdmProperties, ((RowType)clrType).InitializerMetadata);
            }
            else if (Helper.IsRefType(clrType))
            {
                cdmType = new RefType((EntityType)(ConvertOSpaceToCSpaceType(((RefType)clrType).ElementType)));
            }
            else
            {
                cdmType = ((ObjectTypeMapping)GetMap(clrType)).EdmType;
            }
            Debug.Assert((null != cdmType), "null converted clr type");
            return cdmType;
        }
コード例 #10
0
        /// <summary>Convert CSpace TypeMetadata into OSpace TypeMetadata</summary>
        /// <param name="cdmType"></param>
        /// <returns>OSpace type metadata</returns>
        private EdmType ConvertCSpaceToOSpaceType(EdmType cdmType)
        {
            EdmType clrType = null;

            if (Helper.IsCollectionType(cdmType))
            {
                var elemType = ConvertCSpaceToOSpaceType(((CollectionType)cdmType).TypeUsage.EdmType);
                clrType = new CollectionType(elemType);
            }
            else if (Helper.IsRowType(cdmType))
            {
                var clrProperties = new List<EdmProperty>();
                var rowType = (RowType)cdmType;
                foreach (var column in rowType.Properties)
                {
                    var clrPropertyType = ConvertCSpaceToOSpaceType(column.TypeUsage.EdmType);
                    var clrProperty = new EdmProperty(column.Name, TypeUsage.Create(clrPropertyType));
                    clrProperties.Add(clrProperty);
                }
                clrType = new RowType(clrProperties, rowType.InitializerMetadata);
            }
            else if (Helper.IsRefType(cdmType))
            {
                clrType = new RefType((EntityType)ConvertCSpaceToOSpaceType(((RefType)cdmType).ElementType));
            }
            else if (Helper.IsPrimitiveType(cdmType))
            {
                clrType = m_objectCollection.GetMappedPrimitiveType(((PrimitiveType)cdmType).PrimitiveTypeKind);
            }
            else
            {
                clrType = ((ObjectTypeMapping)GetMap(cdmType)).ClrType;
            }
            Debug.Assert((null != clrType), "null converted clr type");
            return clrType;
        }
コード例 #11
0
        /// <summary>
        /// Main code generator method.
        /// </summary>
        /// <param name="namespaceString">Namespace where the class will reside</param>
        /// <param name="className">Generated class name</param>
        /// <param name="attributeNamespace">The 'EdmFunction' attribute parameter</param>
        /// <param name="pascalCaseFunctionNames">If the input function names need to be pascal cased.</param>
        public StringWriter GenerateCode(string namespaceString, string className, string attributeNamespace, Boolean pascalCaseFunctionNames)
        {
            StringWriter newCode = new StringWriter();
            Boolean      isAggregateFunction;
            bool         hasSByteParameterOrReturnType;
            bool         hasStringInParameterName;
            String       separator;

            GenerateFileHeader(newCode, className);
            GenerateUsingStatements(newCode);

            newCode.WriteLine("namespace " + namespaceString);
            newCode.WriteLine("{");

            GenerateClassHeader(newCode, className, attributeNamespace);

            foreach (System.Data.Metadata.Edm.EdmFunction function in _functions)
            {
                isAggregateFunction           = false;
                hasSByteParameterOrReturnType = false;
                hasStringInParameterName      = false;
                separator = "";

                String functionNameToUse = FindCorrectFunctionName(function.Name, pascalCaseFunctionNames);
                GenerateFunctionHeader(newCode, attributeNamespace, function.Name);
                Type returnType = ((PrimitiveType)(function.ReturnParameter.TypeUsage.EdmType)).ClrEquivalentType;

                //Suppress warning that 'SByte' is not CLS-compliant.
                if (returnType == typeof(SByte))
                {
                    hasSByteParameterOrReturnType = true;
                }
                StringBuilder functionSignatureString = new StringBuilder();
                AppendSpaces(functionSignatureString, 8);
                functionSignatureString.Append("public static ");
                WriteType(functionSignatureString, returnType);
                functionSignatureString.Append(functionNameToUse + "(");

                ReadOnlyMetadataCollection <FunctionParameter> functionParameters = function.Parameters;
                Type parameterType;
                foreach (System.Data.Metadata.Edm.FunctionParameter parameter in functionParameters)
                {
                    String parameterNameToUse = parameter.Name;
                    parameterNameToUse = FindCorrectParameterName(parameterNameToUse);

                    //Detect aggregate functions. They have just one parameter and so stub can be generated here.
                    if (parameter.TypeUsage.EdmType.GetType() == typeof(System.Data.Metadata.Edm.CollectionType))
                    {
                        isAggregateFunction = true;
                        if (parameterNameToUse.ToLowerInvariant().Contains("string"))
                        {
                            hasStringInParameterName = true;
                        }

                        System.Data.Metadata.Edm.CollectionType collectionType = (System.Data.Metadata.Edm.CollectionType)parameter.TypeUsage.EdmType;
                        parameterType = ((PrimitiveType)(collectionType.TypeUsage.EdmType)).ClrEquivalentType;
                        //Detect if there is an 'SByte' parameter to suppress non-CLS-compliance warning.
                        //Generate the attribute only once for each function.
                        if (parameterType == typeof(SByte))
                        {
                            hasSByteParameterOrReturnType = true;
                        }

                        //Generate stub for non-nullable input parameters
                        functionSignatureString.Append("IEnumerable<" + parameterType.ToString());
                        //Supress fxcop message and CLS non-compliant attributes
                        GenerateFunctionAttributes(newCode, hasStringInParameterName, hasSByteParameterOrReturnType);
                        //Use the constructed function signature
                        newCode.Write(functionSignatureString.ToString());
                        GenerateAggregateFunctionStub(newCode, parameterType, returnType, parameterNameToUse, false);

                        //Generate stub for nullable input parameters
                        //Special Case: Do not generate nullable stub for input parameter of types Byte[]
                        //and String, since they are nullable.
                        if (!IsNullableType(parameterType))
                        {
                            GenerateFunctionHeader(newCode, attributeNamespace, function.Name);
                            //Supress fxcop message and CLS non-compliant attributes
                            GenerateFunctionAttributes(newCode, hasStringInParameterName, hasSByteParameterOrReturnType);
                            //Use the constructed function signature
                            newCode.Write(functionSignatureString.ToString());
                            GenerateAggregateFunctionStub(newCode, parameterType, returnType, parameterNameToUse, true);
                        }
                    } //End of processing parameters for aggregate functions.
                    //Process each parameter in case of non-aggregate functions.
                    else
                    {
                        parameterType = ((PrimitiveType)(parameter.TypeUsage.EdmType)).ClrEquivalentType;
                        functionSignatureString.Append(separator);
                        WriteType(functionSignatureString, parameterType);
                        functionSignatureString.Append(parameterNameToUse);
                        separator = ", ";
                        //Detect if there is an 'SByte' parameter to suppress non-CLS-compliance warning.
                        if (parameterType == typeof(SByte))
                        {
                            hasSByteParameterOrReturnType = true;
                        }
                        if (parameterNameToUse.ToLowerInvariant().Contains("string"))
                        {
                            hasStringInParameterName = true;
                        }
                    }
                } //End for each parameter

                //Generate stub for Non-aggregate functions after all input parameters are found.
                if (!isAggregateFunction)
                {
                    //Supress fxcop supression and CLS non-compliant attributes
                    GenerateFunctionAttributes(newCode, hasStringInParameterName, hasSByteParameterOrReturnType);
                    newCode.WriteLine(functionSignatureString.ToString() + ")");
                    AppendSpaces(newCode, 8);
                    newCode.WriteLine("{");
                    WriteExceptionStatement(newCode);
                }
            } //End for each function

            AppendSpaces(newCode, 4);
            newCode.WriteLine("}");
            newCode.WriteLine("}");
            newCode.Close();
            return(newCode);
        }