/// <summary>
        /// Creates a set of FunctionImportParameter objects from the parameters passed in.
        /// </summary>
        public static IEnumerable<FunctionImportParameter> Create(IEnumerable<FunctionParameter> parameters, CodeGenerationTools code, MetadataTools ef)
        {
            if (parameters == null)
            {
            throw new ArgumentNullException("parameters");
            }

            if (code == null)
            {
            throw new ArgumentNullException("code");
            }

            if (ef == null)
            {
            throw new ArgumentNullException("ef");
            }

            UniqueIdentifierService unique = new UniqueIdentifierService();
            List<FunctionImportParameter> importParameters = new List<FunctionImportParameter>();
            foreach (FunctionParameter parameter in parameters)
            {
            FunctionImportParameter importParameter = new FunctionImportParameter();
            importParameter.Source = parameter;
            importParameter.RawFunctionParameterName = unique.AdjustIdentifier(code.CamelCase(parameter.Name));
            importParameter.FunctionParameterName = code.Escape(importParameter.RawFunctionParameterName);
            if (parameter.Mode == ParameterMode.In)
            {
                TypeUsage typeUsage = parameter.TypeUsage;
                importParameter.NeedsLocalVariable = true;
                importParameter.FunctionParameterType = code.GetTypeName(typeUsage);
                importParameter.EsqlParameterName = parameter.Name;
                Type clrType = ef.UnderlyingClrType(parameter.TypeUsage.EdmType);
                importParameter.RawClrTypeName = typeUsage.EdmType is EnumType ? code.GetTypeName(typeUsage.EdmType) : code.Escape(clrType);
                importParameter.IsNullableOfT = clrType.IsValueType;
            }
            else
            {
                importParameter.NeedsLocalVariable = false;
                importParameter.FunctionParameterType = "ObjectParameter";
                importParameter.ExecuteParameterName = importParameter.FunctionParameterName;
            }
            importParameters.Add(importParameter);
            }

            // we save the local parameter uniquification for a second pass to make the visible parameters
            // as pretty and sensible as possible
            for (int i = 0; i < importParameters.Count; i++)
            {
            FunctionImportParameter importParameter = importParameters[i];
            if (importParameter.NeedsLocalVariable)
            {
                importParameter.LocalVariableName = unique.AdjustIdentifier(importParameter.RawFunctionParameterName + "Parameter");
                importParameter.ExecuteParameterName = importParameter.LocalVariableName;
            }
            }

            return importParameters;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Entity Frameworks CodeGenerationTools Demo Program.\n");

            //I had problems with accessing Dictionary by [] index, so quickly used these
            //to check in normal C# usage.
            //var tc = new TestCollections();
            //tc.TestCollections2();

            try
            {
                //As this program only reads and interprets the XML within the EDMX,
                //there is no need for a ConnectionString in the App.Config and
                //no connection is made to a database.

                //Since this is a test program, let's assume you are executing from .\bin\Debug
                var currentdirectory = Environment.CurrentDirectory;
                var inputFile = @"..\..\Model1.edmx";
                inputFile = Path.Combine(currentdirectory, inputFile);

                //Demo 1
                //EFFluentUtility is from
                //http://visualstudiogallery.msdn.microsoft.com/5d663b99-ed3b-481d-b7bc-b947d2457e3c
                //By opening the VSIX (DbContextFluentTemplate_V50, which is a ZIP) I've taken a
                //copy of "CSharpDbContextFluent.Mapping.tt" from the ItemTemplate.
                //Then copied the supporting classes from the template and
                //entered here in the CodeGenerationToolsLibrary project as a .Net Class here.
                //I've used the Mapping.tt because it is the most complex,
                //and shows how to obtain the Mapping info used to
                //create the EntityConfiguration from the EDMX.
                //
                // See PropertyToColumnMapping and ManyToManyMappings from
                // MetadataLoadResult
                //
                EF5FluentUtility efu = new EF5FluentUtility();
                MetadataLoadResult mlr = efu.LoadMetadata(inputFile);

                var a = mlr.EdmItems;
                var b = mlr.ManyToManyMappings;
                var c = mlr.PropertyToColumnMapping;
                var d = mlr.TphMappings;

                //Obtain the EntityContainer from the ItemsCollection
                var container = mlr.EdmItems.GetItems<EntityContainer>()[0];

                //Iterate all the EntitySets and Properties
                //EntitySet are as in "People", where the EntityType is "Person"
                foreach (var entityset in container.BaseEntitySets.OfType<EntitySet>().OrderBy(e => e.Name))
                {
                    var entitysetname = entityset.Name;
                    var entityname = entityset.ElementType.Name;
                    var entitytype = entityset.ElementType;
                    var declaringtype = entityset.ElementType.NavigationProperties[0].DeclaringType;

                    //Navigation Properties for a particular Entity
                    var collectionNavigations1 = entityset.ElementType.NavigationProperties.Where(np => np.DeclaringType == entityset.ElementType);

                    // Find m:m relationshipsto configure for a particular Entity
                    var manyManyRelationships = entityset.ElementType.NavigationProperties
                        .Where(np =>
                            //np.DeclaringType is EntityType &&
                            np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
                            && np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
                                // Ensures we only configure from one end.
                                // Convention is to have source on the left, as it would be diagrammatically.
                            && np.RelationshipType.RelationshipEndMembers.First() == np.FromEndMember)
                        .ToArray();

                    //Now process the M:Ms
                    foreach (var navProperty in manyManyRelationships)
                    {
                        var otherNavProperty = navProperty.ToEndMember.GetEntityType().NavigationProperties.Where(n => n.RelationshipType == navProperty.RelationshipType && n != navProperty).Single();
                        var association = (AssociationType)navProperty.RelationshipType;

                        //This did not work in the T4 Template.
                        var mapping1 = mlr.ManyToManyMappings[association];

                        var mapping2 = mlr.ManyToManyMappings.Where(m => m.Key.Name == association.Name).FirstOrDefault().Value;
                        var item1 = mapping1.Item1;

                        //This did not work in the T4 Template.
                        var leftKeyMappings1 = mapping1.Item2[navProperty.ToEndMember];
                        var leftKeyMappings2 = mapping1.Item2.Where(np => np.Key.Name == navProperty.ToEndMember.Name).FirstOrDefault().Value;

                        // Need to ensure that FKs are declared in the same order as the PK properties on each principal type
                        var leftType = (EntityType)navProperty.DeclaringType;
                        var rightType = (EntityType)otherNavProperty.DeclaringType;

                        //Access using Index [navProperty.FromEndMember] did not work within template.
                        var leftKeyMappings = mapping1.Item2.Where(np => np.Key.Name == navProperty.FromEndMember.Name).FirstOrDefault().Value; //[navProperty.FromEndMember];
                        var rightKeyMappings = mapping1.Item2.Where(np => np.Key.Name == otherNavProperty.FromEndMember.Name).FirstOrDefault().Value; //[otherNavProperty.FromEndMember];

                        var left = leftKeyMappings.Where(km => km.Key.Name == "PersonID");
                        var right = rightType.KeyMembers.Select(m => "\"" + rightKeyMappings.Where(km => km.Key.Name == m.Name).FirstOrDefault().Value + "\"").FirstOrDefault();
                    }

                    //Dual OrderBy to bring Keys to top of list
                    //Iterate all properties for this particular Entity.
                    var properties = entityset.ElementType.Properties.OrderBy(s => s.Name).OrderBy(p => entityset.ElementType.KeyMembers.Contains(p) == false).ToArray();
                    foreach (var property in properties)
                    {
                        var propertyname = property.Name;

                        //This did not work in the T4 Template.
                        var mapping1 = mlr.PropertyToColumnMapping[entityset.ElementType];

                        //PropertyToColumnMapping is a collection for ALL Entities, so here the particular Entity needs to be filtered out.
                        //Mapping returned is a complex generic Dictionary.
                        var mapping2 = mlr.PropertyToColumnMapping.Where(k => k.Key == entityset.ElementType).FirstOrDefault().Value;
                        var mapping3 = mlr.PropertyToColumnMapping.Where(k => k.Key.FullName == entityset.ElementType.FullName).FirstOrDefault().Value;

                        var mapping4 = mapping3.Item2.Where(p => p.Key.Name == property.Name).FirstOrDefault().Value;

                        var i1 = mapping1.Item1;
                        var i2 = mapping1.Item2;
                        var mapright = i2[property];
                    }

                }

                //********************************************************************************

                //Demo 2
                //This takes EF.Utility.CS.ttinclude and receates as
                //.net Classes.
                //
                MyTextTransformation tt = new MyTextTransformation();
                CodeGenerationTools code = new CodeGenerationTools(tt);

                CodeRegion cregion = new CodeRegion(tt, 1);
                MetadataTools mtool = new MetadataTools(tt);
                MetadataLoader mloader = new MetadataLoader(tt);

                var ItemCollection = mloader.CreateEdmItemCollection(inputFile);

                var Container = ItemCollection.GetItems<EntityContainer>()[0];
                Console.WriteLine(String.Format("Container Name: {0}", Container.Name));
                Console.WriteLine(String.Format("Model Namespace: {0}", mloader.GetModelNamespace(inputFile)));
                Console.WriteLine(String.Format("No Of Items in ItemsCollection: {0}\n", ItemCollection.Count));
                Console.WriteLine("Press any key to continue.\n"); Console.ReadKey();

                foreach (var i in ItemCollection) { Console.WriteLine(String.Format("Item: {0}, {1}", i.ToString(), i.BuiltInTypeKind.ToString())); }
                Console.WriteLine("Press any key to continue.\n"); Console.ReadKey();

                EdmItemCollection edmItemCollection = null; ;
                var ret = mloader.TryCreateEdmItemCollection(inputFile, out edmItemCollection);

                StoreItemCollection storeItemCollection = null;
                ret = mloader.TryCreateStoreItemCollection(inputFile, out storeItemCollection);

                StorageMappingItemCollection storageMappingItemCollection = null;
                ret = mloader.TryCreateStorageMappingItemCollection(inputFile, edmItemCollection, storeItemCollection, out storageMappingItemCollection);
                foreach (var i in storageMappingItemCollection) { Console.WriteLine(String.Format("Item: {0}, {1}", i.ToString(), i.BuiltInTypeKind.ToString())); }
                DataSpace ds = storageMappingItemCollection.DataSpace;

                MetadataWorkspace metadataWorkspace = null;
                ret = mloader.TryLoadAllMetadata(inputFile, out metadataWorkspace);

                //Get the schema "dbo" from a particular Entity.
                EntityContainer ec = storeItemCollection.GetItems<EntityContainer>().First();
                EntitySet eset = ec.GetEntitySetByName(code.Escape("People"), true);
                string schemaName1 = eset.MetadataProperties["Schema"].Value.ToString();

                //Get the schema "dbo" from any Entity. I guess the schema will be same for all?!
                EntitySetBase fes = ec.BaseEntitySets.FirstOrDefault();
                string schemaName2 = fes.MetadataProperties["Schema"].Value.ToString();

                var edmxSchema = EDMXchema.GetSchemaElement(inputFile);

                Console.WriteLine("Press any key to continue.\n"); Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.WriteLine("Press any key to quit.");
            Console.ReadKey();

            // var loadResult = LoadMetadata(inputFile);
        }