Ejemplo n.º 1
0
    /// <summary>
    /// Sets the expected column types for a given function command tree
    /// </summary>
    private void SetFunctionExpectedTypes(DbFunctionCommandTree tree, EFMySqlCommand cmd)
    {
      if (tree.ResultType != null)
      {
        Debug.Assert(tree.ResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType,
            Resources.WrongFunctionResultType);

        CollectionType collectionType = (CollectionType)(tree.ResultType.EdmType);
        EdmType elementType = collectionType.TypeUsage.EdmType;

        if (elementType.BuiltInTypeKind == BuiltInTypeKind.RowType)
        {
          ReadOnlyMetadataCollection<EdmMember> members = ((RowType)elementType).Members;
          cmd.ColumnTypes = new PrimitiveType[members.Count];

          for (int ordinal = 0; ordinal < members.Count; ordinal++)
          {
            EdmMember member = members[ordinal];
            PrimitiveType primitiveType = (PrimitiveType)member.TypeUsage.EdmType;
            cmd.ColumnTypes[ordinal] = primitiveType;
          }

        }
        else if (elementType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType)
        {
          cmd.ColumnTypes = new PrimitiveType[1];
          cmd.ColumnTypes[0] = (PrimitiveType)elementType;
        }
        else
        {
          Debug.Fail(Resources.WrongFunctionResultType);
        }
      }
    }
Ejemplo n.º 2
0
        /// <summary>
        /// don't let this be constructed publicly;
        /// </summary>
        /// <exception cref="EntityCommandCompilationException">Cannot prepare the command definition for execution; consult the InnerException for more information.</exception>
        /// <exception cref="NotSupportedException">The ADO.NET Data Provider you are using does not support CommandTrees.</exception>
        internal EntityCommandDefinition(DbProviderFactory storeProviderFactory, DbCommandTree commandTree) {
            EntityUtil.CheckArgumentNull(storeProviderFactory, "storeProviderFactory");
            EntityUtil.CheckArgumentNull(commandTree, "commandTree");

            DbProviderServices storeProviderServices = DbProviderServices.GetProviderServices(storeProviderFactory);

            try {
                if (DbCommandTreeKind.Query == commandTree.CommandTreeKind) {
                    // Next compile the plan for the command tree
                    List<ProviderCommandInfo> mappedCommandList = new List<ProviderCommandInfo>();
                    ColumnMap columnMap;
                    int columnCount;
                    PlanCompiler.Compile(commandTree, out mappedCommandList, out columnMap, out columnCount, out _entitySets);
                    _columnMapGenerators = new IColumnMapGenerator[] {new ConstantColumnMapGenerator(columnMap, columnCount)};
                    // Note: we presume that the first item in the ProviderCommandInfo is the root node;
                    Debug.Assert(mappedCommandList.Count > 0, "empty providerCommandInfo collection and no exception?"); // this shouldn't ever happen.

                    // Then, generate the store commands from the resulting command tree(s)
                    _mappedCommandDefinitions = new List<DbCommandDefinition>(mappedCommandList.Count);

                    foreach (ProviderCommandInfo providerCommandInfo in mappedCommandList) {
                        DbCommandDefinition providerCommandDefinition = storeProviderServices.CreateCommandDefinition(providerCommandInfo.CommandTree);

                        if (null == providerCommandDefinition) {
                            throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.ProviderReturnedNullForCreateCommandDefinition);
                        }
                        _mappedCommandDefinitions.Add(providerCommandDefinition);
                    }
                }
                else {
                    Debug.Assert(DbCommandTreeKind.Function == commandTree.CommandTreeKind, "only query and function command trees are supported");
                    DbFunctionCommandTree entityCommandTree = (DbFunctionCommandTree)commandTree;

                    // Retrieve mapping and metadata information for the function import.
                    FunctionImportMappingNonComposable mapping = GetTargetFunctionMapping(entityCommandTree);
                    IList<FunctionParameter> returnParameters = entityCommandTree.EdmFunction.ReturnParameters;
                    int resultSetCount = returnParameters.Count > 1 ? returnParameters.Count : 1;
                    _columnMapGenerators = new IColumnMapGenerator[resultSetCount];
                    TypeUsage storeResultType = DetermineStoreResultType(entityCommandTree.MetadataWorkspace, mapping, 0, out _columnMapGenerators[0]);
                    for (int i = 1; i < resultSetCount; i++)
                    {
                        DetermineStoreResultType(entityCommandTree.MetadataWorkspace, mapping, i, out _columnMapGenerators[i]);
                    }
                    // Copy over parameters (this happens through a more indirect route in the plan compiler, but
                    // it happens nonetheless)
                    List<KeyValuePair<string, TypeUsage>> providerParameters = new List<KeyValuePair<string, TypeUsage>>();
                    foreach (KeyValuePair<string, TypeUsage> parameter in entityCommandTree.Parameters)
                    {
                        providerParameters.Add(parameter);
                    }

                    // Construct store command tree usage.
                    DbFunctionCommandTree providerCommandTree = new DbFunctionCommandTree(entityCommandTree.MetadataWorkspace, DataSpace.SSpace,
                        mapping.TargetFunction, storeResultType, providerParameters);
                                        
                    DbCommandDefinition storeCommandDefinition = storeProviderServices.CreateCommandDefinition(providerCommandTree);
                    _mappedCommandDefinitions = new List<DbCommandDefinition>(1) { storeCommandDefinition };

                    EntitySet firstResultEntitySet = mapping.FunctionImport.EntitySets.FirstOrDefault();
                    if (firstResultEntitySet != null)
                    {
                        _entitySets = new Set<EntitySet>();
                        _entitySets.Add(mapping.FunctionImport.EntitySets.FirstOrDefault());
                        _entitySets.MakeReadOnly();
                    }
                }

                // Finally, build a list of the parameters that the resulting command should have;
                List<EntityParameter> parameterList = new List<EntityParameter>();

                foreach (KeyValuePair<string, TypeUsage> queryParameter in commandTree.Parameters) {
                    EntityParameter parameter = CreateEntityParameterFromQueryParameter(queryParameter);
                    parameterList.Add(parameter);
                }

                _parameters = new System.Collections.ObjectModel.ReadOnlyCollection<EntityParameter>(parameterList);
            }
            catch (EntityCommandCompilationException) {
                // No need to re-wrap EntityCommandCompilationException
                throw;
            }
            catch (Exception e) {
                // we should not be wrapping all exceptions
                if (EntityUtil.IsCatchableExceptionType(e)) {
                    // we don't wan't folks to have to know all the various types of exceptions that can 
                    // occur, so we just rethrow a CommandDefinitionException and make whatever we caught  
                    // the inner exception of it.
                    throw EntityUtil.CommandCompilation(System.Data.Entity.Strings.EntityClient_CommandDefinitionPreparationFailed, e);
                }
                throw;
            }
        }
        protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
        {
            EntityUtil.CheckArgumentNull(functionTree, "functionTree");

        }
Ejemplo n.º 4
0
        /// <summary>
        /// Retrieves mapping for the given C-Space functionCommandTree
        /// </summary>
        private static FunctionImportMappingNonComposable GetTargetFunctionMapping(DbFunctionCommandTree functionCommandTree)
        {
            Debug.Assert(functionCommandTree.DataSpace == DataSpace.CSpace, "map from CSpace->SSpace function");
            Debug.Assert(functionCommandTree != null, "null functionCommandTree");
            Debug.Assert(!functionCommandTree.EdmFunction.IsComposableAttribute, "functionCommandTree.EdmFunction must be non-composable.");

            // Find mapped store function.
            FunctionImportMapping targetFunctionMapping;
            if (!functionCommandTree.MetadataWorkspace.TryGetFunctionImportMapping(functionCommandTree.EdmFunction, out targetFunctionMapping))
            {
                throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.EntityClient_UnmappedFunctionImport(functionCommandTree.EdmFunction.FullName));
            }
            return (FunctionImportMappingNonComposable)targetFunctionMapping;
        }
        // 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;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Ensures we have the command tree, either the user passed us the tree, or an eSQL statement that we need to parse
        /// </summary>
        private void MakeCommandTree()
        {
            // We must have a connection before we come here
            Debug.Assert(_connection != null);

            // Do the work only if we don't have a command tree yet
            if (_preparedCommandTree == null)
            {
                DbCommandTree resultTree = null;
                if (_commandTreeSetByUser != null)
                {
                    resultTree = _commandTreeSetByUser;
                }
                else if (CommandType.Text == CommandType)
                {
                    if (!string.IsNullOrEmpty(_esqlCommandText))
                    {
                        // The perspective to be used for the query compilation
                        Perspective perspective = new ModelPerspective(_connection.GetMetadataWorkspace());

                        // get a dictionary of names and typeusage from entity parameter collection
                        var queryParams = GetParameterTypeUsage();

                        resultTree = CqlQuery.Compile(
                            _esqlCommandText,
                            perspective,
                            null /*parser option - use default*/,
                            queryParams.Select(paramInfo => paramInfo.Value.Parameter(paramInfo.Key))).CommandTree;
                    }
                    else
                    {
                        // We have no command text, no command tree, so throw an exception
                        if (_isCommandDefinitionBased)
                        {
                            // This command was based on a prepared command definition and has no command text,
                            // so reprepare is not possible. To create a new command with different parameters
                            // requires creating a new entity command definition and calling it's CreateCommand method.
                            throw new InvalidOperationException(Strings.EntityClient_CannotReprepareCommandDefinitionBasedCommand);
                        }
                        else
                        {
                            throw new InvalidOperationException(Strings.EntityClient_NoCommandText);
                        }
                    }
                }
                else if (CommandType.StoredProcedure == CommandType)
                {
                    // get a dictionary of names and typeusage from entity parameter collection
                    IEnumerable<KeyValuePair<string, TypeUsage>> queryParams = GetParameterTypeUsage();
                    var function = DetermineFunctionImport();
                    resultTree = new DbFunctionCommandTree(Connection.GetMetadataWorkspace(), DataSpace.CSpace, function, null, queryParams);
                }

                // After everything is good and succeeded, assign the result to our field
                _preparedCommandTree = resultTree;
            }
        }
 protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
 {
     //Contract.Requires(functionTree != null);
 }
 protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
 {
     EntityUtil.CheckArgumentNull(functionTree, "functionTree");
 }