/// <summary>
 ///     Constructor for testing/mocking purposes.
 /// </summary>
 protected EntityCommandDefinition(
     BridgeDataReaderFactory factory   = null,
     ColumnMapFactory columnMapFactory = null,
     List <DbCommandDefinition> mappedCommandDefinitions = null)
 {
     _bridgeDataReaderFactory  = factory ?? new BridgeDataReaderFactory();
     _columnMapFactory         = columnMapFactory ?? new ColumnMapFactory();
     _mappedCommandDefinitions = mappedCommandDefinitions;
 }
 internal FunctionColumnMapGenerator(
     FunctionImportMappingNonComposable mapping,
     int resultSetIndex,
     EntitySet entitySet,
     StructuralType baseStructuralType,
     ColumnMapFactory columnMapFactory)
 {
     _mapping            = mapping;
     _entitySet          = entitySet;
     _baseStructuralType = baseStructuralType;
     _resultSetIndex     = resultSetIndex;
     _columnMapFactory   = columnMapFactory;
 }
        internal EntityCommandDefinition(
            DbProviderFactory storeProviderFactory, DbCommandTree commandTree, IDbDependencyResolver resolver = null,
            BridgeDataReaderFactory bridgeDataReaderFactory = null, ColumnMapFactory columnMapFactory = null)
        {
            DebugCheck.NotNull(storeProviderFactory);
            DebugCheck.NotNull(commandTree);

            _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);

                        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;
            }
        }
 ColumnMap IColumnMapGenerator.CreateColumnMap(DbDataReader reader)
 {
     return(ColumnMapFactory.CreateFunctionImportStructuralTypeColumnMap(reader, _mapping, _resultSetIndex, _entitySet, _baseStructuralType));
 }
 internal EntityCommandDefinition(
     DbProviderFactory storeProviderFactory,
     DbCommandTree commandTree,
     DbInterceptionContext interceptionContext,
     IDbDependencyResolver resolver = null,
     BridgeDataReaderFactory bridgeDataReaderFactory = null,
     ColumnMapFactory columnMapFactory = null)
 {
     this._bridgeDataReaderFactory = bridgeDataReaderFactory ?? new BridgeDataReaderFactory((Translator)null);
     this._columnMapFactory        = columnMapFactory ?? new ColumnMapFactory();
     this._storeProviderServices   = (resolver != null ? resolver.GetService <DbProviderServices>((object)storeProviderFactory.GetProviderInvariantName()) : (DbProviderServices)null) ?? storeProviderFactory.GetProviderServices();
     try
     {
         if (commandTree.CommandTreeKind == DbCommandTreeKind.Query)
         {
             List <ProviderCommandInfo> providerCommands = new List <ProviderCommandInfo>();
             ColumnMap resultColumnMap;
             int       columnCount;
             System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Compile(commandTree, out providerCommands, out resultColumnMap, out columnCount, out this._entitySets);
             this._columnMapGenerators = new EntityCommandDefinition.IColumnMapGenerator[1]
             {
                 (EntityCommandDefinition.IColumnMapGenerator) new EntityCommandDefinition.ConstantColumnMapGenerator(resultColumnMap, columnCount)
             };
             this._mappedCommandDefinitions = new List <DbCommandDefinition>(providerCommands.Count);
             foreach (ProviderCommandInfo providerCommandInfo in providerCommands)
             {
                 DbCommandDefinition commandDefinition = this._storeProviderServices.CreateCommandDefinition(providerCommandInfo.CommandTree, interceptionContext);
                 if (commandDefinition == null)
                 {
                     throw new ProviderIncompatibleException(Strings.ProviderReturnedNullForCreateCommandDefinition);
                 }
                 this._mappedCommandDefinitions.Add(commandDefinition);
             }
         }
         else
         {
             DbFunctionCommandTree functionCommandTree = (DbFunctionCommandTree)commandTree;
             FunctionImportMappingNonComposable targetFunctionMapping = EntityCommandDefinition.GetTargetFunctionMapping(functionCommandTree);
             IList <FunctionParameter>          returnParameters      = (IList <FunctionParameter>)functionCommandTree.EdmFunction.ReturnParameters;
             int length = returnParameters.Count > 1 ? returnParameters.Count : 1;
             this._columnMapGenerators = new EntityCommandDefinition.IColumnMapGenerator[length];
             TypeUsage storeResultType = this.DetermineStoreResultType(targetFunctionMapping, 0, out this._columnMapGenerators[0]);
             for (int resultSetIndex = 1; resultSetIndex < length; ++resultSetIndex)
             {
                 this.DetermineStoreResultType(targetFunctionMapping, resultSetIndex, out this._columnMapGenerators[resultSetIndex]);
             }
             List <KeyValuePair <string, TypeUsage> > keyValuePairList = new List <KeyValuePair <string, TypeUsage> >();
             foreach (KeyValuePair <string, TypeUsage> parameter in functionCommandTree.Parameters)
             {
                 keyValuePairList.Add(parameter);
             }
             this._mappedCommandDefinitions = new List <DbCommandDefinition>(1)
             {
                 this._storeProviderServices.CreateCommandDefinition((DbCommandTree) new DbFunctionCommandTree(functionCommandTree.MetadataWorkspace, DataSpace.SSpace, targetFunctionMapping.TargetFunction, storeResultType, (IEnumerable <KeyValuePair <string, TypeUsage> >)keyValuePairList))
             };
             if (targetFunctionMapping.FunctionImport.EntitySets.FirstOrDefault <EntitySet>() != null)
             {
                 this._entitySets = new Set <EntitySet>();
                 this._entitySets.Add(targetFunctionMapping.FunctionImport.EntitySets.FirstOrDefault <EntitySet>());
                 this._entitySets.MakeReadOnly();
             }
         }
         List <EntityParameter> entityParameterList = new List <EntityParameter>();
         foreach (KeyValuePair <string, TypeUsage> parameter in commandTree.Parameters)
         {
             EntityParameter fromQueryParameter = EntityCommandDefinition.CreateEntityParameterFromQueryParameter(parameter);
             entityParameterList.Add(fromQueryParameter);
         }
         this._parameters = new ReadOnlyCollection <EntityParameter>((IList <EntityParameter>)entityParameterList);
     }
     catch (EntityCommandCompilationException ex)
     {
         throw;
     }
     catch (Exception ex)
     {
         if (ex.IsCatchableExceptionType())
         {
             throw new EntityCommandCompilationException(Strings.EntityClient_CommandDefinitionPreparationFailed, ex);
         }
         throw;
     }
 }