private void MapFunctions(LoadMethodSessionState session, EntityContainer modelEntityContainer)
        {
            if (_storeFunctions == null || _storeFunctions.Length == 0 || _targetEntityFrameworkVersion < EntityFrameworkVersions.Version3)
            {
                return;
            }

            //
            // Create function imports and appropriate complex types for return parameters and add them to the item collection (session.EdmItemCollection).
            // Create and add function mappings.
            //

            var interestingStoreFunctions = _storeFunctions.Where(
                f => f.IsComposableAttribute &&
                     !f.AggregateAttribute &&
                     f.Parameters.All(p => p.Mode == ParameterMode.In));
            foreach (var storeFunction in interestingStoreFunctions)
            {
                RowType tvfReturnType = TypeHelpers.GetTvfReturnType(storeFunction);
                if (tvfReturnType == null)
                {
                    continue;
                }

                // Create function import name.
                string functionImportName = CreateModelName(storeFunction.Name, session.UsedEntityContainerItemNames);
               
                // Create function import parameters.
                UniqueIdentifierService usedParameterNames = new UniqueIdentifierService(false);
                var parameters = storeFunction.Parameters.Select(p => CreateFunctionImportParameter(p, usedParameterNames)).ToArray();
                var failedStoreParameterName = storeFunction.Parameters.Select(p => p.Name).Except(parameters.Select(p => p.Name)).FirstOrDefault();
                if (failedStoreParameterName != null)
                {
                    session.AddError(Strings.UnableToGenerateFunctionImportParameterName(failedStoreParameterName, storeFunction.Identity),
                        ModelBuilderErrorCode.UnableToGenerateFunctionImportParameterName, EdmSchemaErrorSeverity.Warning, null);
                    continue;
                }

                // Create new complex type and register it in the item collection.
                var complexType = CreateModelComplexTypeForTvfResult(session, functionImportName, tvfReturnType);
                complexType.SetReadOnly();
                session.EdmItemCollection.AddInternal(complexType);

                var collectionType = complexType.GetCollectionType();
                collectionType.SetReadOnly();
                var returnTypeUsage = TypeUsage.Create(collectionType);

                // Create function import and register it in the item collection.
                var functionImport = new EdmFunction(functionImportName, _modelEntityContainerName, DataSpace.CSpace, new EdmFunctionPayload()
                {
                    Name = functionImportName,
                    NamespaceName = _namespaceName,
                    ReturnParameters = new FunctionParameter[] {new FunctionParameter(EdmConstants.ReturnType, returnTypeUsage, ParameterMode.ReturnValue)},
                    Parameters = parameters,
                    DataSpace = DataSpace.CSpace,
                    IsComposable = true,
                    IsFunctionImport = true
                });
                functionImport.SetReadOnly();
                modelEntityContainer.AddFunctionImport(functionImport);

                // Add mapping tuple.
                session.MappingLookups.StoreFunctionToFunctionImport.Add(Tuple.Create(storeFunction, functionImport));
            }
        }
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] //For EdmItemCollection constructor call.  
                                                                            //Since we pass in empty collection for paths, we do not have any resource exposure here.                                                               
        private IList<EdmSchemaError> InternalGenerateMetadata()
        {
            if (_modelEntityContainer != null)
            {
                _modelEntityContainer = null;
                _mappingLookups = null;
                _edmItemCollection = null;
            }

            LoadMethodSessionState session = new LoadMethodSessionState();

            try
            {
                session.EdmItemCollection = new EdmItemCollection();
                if (this.GenerateForeignKeyProperties && this._targetEntityFrameworkVersion < EntityFrameworkVersions.Version2)
                {
                    session.AddError(Strings.UnableToGenerateForeignKeyPropertiesForV1, ModelBuilderErrorCode.UnableToGenerateForeignKeyPropertiesForV1, EdmSchemaErrorSeverity.Error, null);
                    return session.Errors;
                }

                List<AssociationSet> storeAssociationSets = new List<AssociationSet>();
                CollectAllFkProperties(session);

                EntityContainer modelEntityContainer = new EntityContainer(_modelEntityContainerName, DataSpace.CSpace);

                // create the EntityTypes and EntitySets, and save up the AssociationSets for later.
                foreach (EntitySetBase storeSet in _storeEntityContainer.BaseEntitySets)
                {
                    switch (storeSet.BuiltInTypeKind)
                    {
                        case BuiltInTypeKind.AssociationSet:
                            // save these, and create them after the EntityTypes and EntitySets have been created
                            string errorMessage;
                            if (this.GenerateForeignKeyProperties || !EntityStoreSchemaGenerator.IsFkPartiallyContainedInPK(((AssociationSet)storeSet).ElementType, out errorMessage))
                            {
                                storeAssociationSets.Add((AssociationSet)storeSet);
                            }
                            else
                            {
                                session.AddError(errorMessage, ModelBuilderErrorCode.UnsupportedForeinKeyPattern, EdmSchemaErrorSeverity.Error, null);
                            }
                            break;
                        case BuiltInTypeKind.EntitySet:
                            EntitySet set = (EntitySet)storeSet;
                            session.CandidateCollapsedAssociations.Add(set, new OneToOneMappingSerializer.CollapsedEntityAssociationSet(set));
                            break;
                        default:
                            // error
                            throw EDesignUtil.MissingGenerationPatternForType(storeSet.BuiltInTypeKind);
                    }
                }

                foreach (AssociationSet storeAssociationSet in storeAssociationSets)
                {
                    SaveAssociationForCollapsedAssociationCandidate(session, storeAssociationSet);
                }

                Set<AssociationSet> associationSetsFromCollapseCandidateRejects = new Set<AssociationSet>();
                IEnumerable<OneToOneMappingSerializer.CollapsedEntityAssociationSet> invalidCandidates = FindAllInvalidCollapsedAssociationCandidates(session);

                // now that we have gone through all of the association sets, 
                foreach (OneToOneMappingSerializer.CollapsedEntityAssociationSet collapsed in invalidCandidates)
                {
                    session.CandidateCollapsedAssociations.Remove(collapsed.EntitySet);

                    // just create the entity set and save the association set to be added later
                    EntitySet entitySet = CreateModelEntitySet(session, collapsed.EntitySet);
                    modelEntityContainer.AddEntitySetBase(entitySet);
                    associationSetsFromCollapseCandidateRejects.AddRange(collapsed.AssociationSets);                        
                }

                // create all the associations for the invalid collapsed entity association candidates
                foreach (AssociationSet storeAssociationSet in (IEnumerable<AssociationSet>)associationSetsFromCollapseCandidateRejects)
                {
                    if (!IsAssociationPartOfCandidateCollapsedAssociation(session, storeAssociationSet))
                    {
                        AssociationSet set = CreateModelAssociationSet(session, storeAssociationSet);
                        modelEntityContainer.AddEntitySetBase(set);
                    }
                }
                
                // save the set that needs to be created and mapped
                session.MappingLookups.CollapsedEntityAssociationSets.AddRange(session.CandidateCollapsedAssociations.Values);

                // do this in a seperate loop so we are sure all the necessary EntitySets have been created
                foreach (OneToOneMappingSerializer.CollapsedEntityAssociationSet collapsed in session.MappingLookups.CollapsedEntityAssociationSets)
                {
                    AssociationSet set = CreateModelAssociationSet(session, collapsed);
                    modelEntityContainer.AddEntitySetBase(set);
                }
                if (this._targetEntityFrameworkVersion >= EntityFrameworkVersions.Version2)
                {
                    Debug.Assert(EntityFrameworkVersions.Latest == EntityFrameworkVersions.Version3, "Did you add a new framework version");
                    // add LazyLoadingEnabled=true to the EntityContainer
                    MetadataProperty lazyLoadingAttribute =
                        new MetadataProperty(
                            DesignXmlConstants.EdmAnnotationNamespace + ":" + DesignXmlConstants.LazyLoadingEnabled,
                            TypeUsage.CreateStringTypeUsage(
                                PrimitiveType.GetEdmPrimitiveType(
                                    PrimitiveTypeKind.String),
                                    false,
                                    false),
                            true);
                    modelEntityContainer.AddMetadataProperties(new List<MetadataProperty>() { lazyLoadingAttribute });
                    this._hasAnnotationNamespace = true;
                }

                // Map store functions to function imports.
                MapFunctions(session, modelEntityContainer);
                
                if (!EntityStoreSchemaGenerator.HasErrorSeverityErrors(session.Errors))
                {
                    // add them to the collection so they will work if someone wants to use the collection
                    foreach (EntityType type in session.MappingLookups.StoreEntityTypeToModelEntityType.Values)
                    {
                        type.SetReadOnly();
                        session.EdmItemCollection.AddInternal(type);
                    }

                    foreach (AssociationType type in session.MappingLookups.StoreAssociationTypeToModelAssociationType.Values)
                    {
                        type.SetReadOnly();
                        session.EdmItemCollection.AddInternal(type);
                    }

                    foreach (OneToOneMappingSerializer.CollapsedEntityAssociationSet set in session.MappingLookups.CollapsedEntityAssociationSets)
                    {
                        set.ModelAssociationSet.ElementType.SetReadOnly();
                        session.EdmItemCollection.AddInternal(set.ModelAssociationSet.ElementType);
                    }
                    modelEntityContainer.SetReadOnly();
                    session.EdmItemCollection.AddInternal(modelEntityContainer);

                    _modelEntityContainer = modelEntityContainer;
                    _mappingLookups = session.MappingLookups;
                    _edmItemCollection = session.EdmItemCollection;
                }

            }
            catch (Exception e)
            {
                if (MetadataUtil.IsCatchableExceptionType(e))
                {
                    // an exception in the code is definitely an error
                    string message = EDesignUtil.GetMessagesFromEntireExceptionChain(e);
                    session.AddError(message,
                    ModelBuilderErrorCode.UnknownError,
                    EdmSchemaErrorSeverity.Error,
                    e);
                }
                else
                {
                    throw;
                }

            }
            return session.Errors;
        }