private void GetAffectedEntitySets(System.Data.Entity.Core.Common.CommandTrees.DbCommandTree commandTree)
        {
            System.Data.Entity.Core.Common.CommandTrees.DbExpressionVisitor visitor   = new FindAffectedEntitySetsVisitor(this.affectedEntitySets, this.functionsUsed);
            System.Data.Entity.Core.Common.CommandTrees.DbQueryCommandTree  queryTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbQueryCommandTree;
            if (queryTree != null)
            {
                queryTree.Query.Accept(visitor);
                return;
            }

            System.Data.Entity.Core.Common.CommandTrees.DbFunctionCommandTree fxnTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbFunctionCommandTree;
            if (fxnTree != null)
            {
                this.IsStoredProcedure = true;
                return;
            }

            System.Data.Entity.Core.Common.CommandTrees.DbUpdateCommandTree updateTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbUpdateCommandTree;
            if (updateTree != null)
            {
                this.IsModification = true;
                updateTree.Target.Expression.Accept(visitor);
                updateTree.Predicate.Accept(visitor);
                if (updateTree.Returning != null)
                {
                    updateTree.Returning.Accept(visitor);
                }

                return;
            }

            System.Data.Entity.Core.Common.CommandTrees.DbInsertCommandTree insertTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbInsertCommandTree;
            if (insertTree != null)
            {
                this.IsModification = true;
                insertTree.Target.Expression.Accept(visitor);
                if (insertTree.Returning != null)
                {
                    insertTree.Returning.Accept(visitor);
                }

                return;
            }

            System.Data.Entity.Core.Common.CommandTrees.DbDeleteCommandTree deleteTree = commandTree as System.Data.Entity.Core.Common.CommandTrees.DbDeleteCommandTree;
            if (deleteTree != null)
            {
                this.IsModification = true;
                deleteTree.Target.Expression.Accept(visitor);
                if (deleteTree.Predicate != null)
                {
                    deleteTree.Predicate.Accept(visitor);
                }

                return;
            }

            throw new NotSupportedException("Command tree type " + commandTree.GetType() + " is not supported.");
        }
 protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
 {
     Contract.Requires(functionTree != null);
 }
        internal EntityCommandDefinition(
            DbProviderFactory storeProviderFactory,
            DbCommandTree commandTree, 
            DbInterceptionContext interceptionContext,
            IDbDependencyResolver resolver = null,
            BridgeDataReaderFactory bridgeDataReaderFactory = null,
            ColumnMapFactory columnMapFactory = null)
        {
            DebugCheck.NotNull(storeProviderFactory);
            DebugCheck.NotNull(commandTree);
            DebugCheck.NotNull(interceptionContext);

            _bridgeDataReaderFactory = bridgeDataReaderFactory ?? new BridgeDataReaderFactory();
            _columnMapFactory = columnMapFactory ?? new ColumnMapFactory();

            _storeProviderServices =
                (resolver != null
                     ? resolver.GetService<DbProviderServices>(storeProviderFactory.GetProviderInvariantName())
                     : null) ??
                storeProviderFactory.GetProviderServices();

            try
            {
                if (DbCommandTreeKind.Query
                    == commandTree.CommandTreeKind)
                {
                    // Next compile the plan for the command tree
                    var 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 (var providerCommandInfo in mappedCommandList)
                    {
                        var providerCommandDefinition = _storeProviderServices.CreateCommandDefinition(
                            providerCommandInfo.CommandTree, interceptionContext);

                        if (null == providerCommandDefinition)
                        {
                            throw new ProviderIncompatibleException(Strings.ProviderReturnedNullForCreateCommandDefinition);
                        }

                        _mappedCommandDefinitions.Add(providerCommandDefinition);
                    }
                }
                else
                {
                    Debug.Assert(
                        DbCommandTreeKind.Function == commandTree.CommandTreeKind, "only query and function command trees are supported");
                    var entityCommandTree = (DbFunctionCommandTree)commandTree;

                    // Retrieve mapping and metadata information for the function import.
                    var mapping = GetTargetFunctionMapping(entityCommandTree);
                    IList<FunctionParameter> returnParameters = entityCommandTree.EdmFunction.ReturnParameters;
                    var resultSetCount = returnParameters.Count > 1 ? returnParameters.Count : 1;
                    _columnMapGenerators = new IColumnMapGenerator[resultSetCount];
                    var storeResultType = DetermineStoreResultType(mapping, 0, out _columnMapGenerators[0]);
                    for (var i = 1; i < resultSetCount; i++)
                    {
                        DetermineStoreResultType(mapping, i, out _columnMapGenerators[i]);
                    }

                    // Copy over parameters (this happens through a more indirect route in the plan compiler, but
                    // it happens nonetheless)
                    var providerParameters = new List<KeyValuePair<string, TypeUsage>>();
                    foreach (var parameter in entityCommandTree.Parameters)
                    {
                        providerParameters.Add(parameter);
                    }

                    // Construct store command tree usage.
                    var providerCommandTree = new DbFunctionCommandTree(
                        entityCommandTree.MetadataWorkspace, DataSpace.SSpace,
                        mapping.TargetFunction, storeResultType, providerParameters);

                    var storeCommandDefinition = _storeProviderServices.CreateCommandDefinition(providerCommandTree);
                    _mappedCommandDefinitions = new List<DbCommandDefinition>(1)
                        {
                            storeCommandDefinition
                        };

                    var 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;
                var parameterList = new List<EntityParameter>();

                foreach (var queryParameter in commandTree.Parameters)
                {
                    var parameter = CreateEntityParameterFromQueryParameter(queryParameter);
                    parameterList.Add(parameter);
                }

                _parameters = new ReadOnlyCollection<EntityParameter>(parameterList);
            }
            catch (EntityCommandCompilationException)
            {
                // No need to re-wrap EntityCommandCompilationException
                throw;
            }
            catch (Exception e)
            {
                // we should not be wrapping all exceptions
                if (e.IsCatchableExceptionType())
                {
                    // 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 new EntityCommandCompilationException(Strings.EntityClient_CommandDefinitionPreparationFailed, e);
                }

                throw;
            }
        }
        /// <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");
            DebugCheck.NotNull(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 new InvalidOperationException(Strings.EntityClient_UnmappedFunctionImport(functionCommandTree.EdmFunction.FullName));
            }
            return (FunctionImportMappingNonComposable)targetFunctionMapping;
        }
 /// <summary>Implements the visitor pattern for the function command tree.</summary>
 /// <param name="functionTree">The function command tree.</param>
 protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
 {
     Check.NotNull(functionTree, "functionTree");
 }
    /// <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);
        }
      }
    }
示例#7
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 DbCommandTree MakeCommandTree()
        {
            // We must have a connection before we come here
            Debug.Assert(_connection != 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);
            }

            return resultTree;
        }
 /// <summary>Implements the visitor pattern for the function command tree.</summary>
 /// <param name="functionTree">The function command tree.</param>
 protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
 {
     Check.NotNull <DbFunctionCommandTree>(functionTree, nameof(functionTree));
 }
 /// <summary>Implements the visitor pattern for the function command tree.</summary>
 /// <param name="functionTree">The function command tree.</param>
 protected virtual void VisitFunctionCommandTree(DbFunctionCommandTree functionTree)
 {
     Check.NotNull(functionTree, "functionTree");
 }