Class for field property data. Needed for dynamic object factory.
Inheritance: DynamicPropertyData
        /// <summary>	Creates the model. </summary>
        ///
        /// <returns>	The new model. </returns>
        private static DbCompiledModel CreateModel()
        {
            // Create a model + register types to it.
            var modelBuilder = new DbModelBuilder();
            modelBuilder.Conventions.Remove<PluralizingEntitySetNameConvention>(); //For generating Entities without 's' at the end
            DbCompiledModel compiledDatabaseModel = null;

            try
            {
                #region Read Schema and Add to Model

                // https://www.nuget.org/packages/DatabaseSchemaReader/
                using (var dbReader = new DatabaseReader(cConnectionStringSettings.ConnectionString, cConnectionStringSettings.ProviderName, DynamicContext.cDefaultSchemaName))
                {
                    var schema = dbReader.ReadAll();
                    var dynamicClassFactory = new DynamicClassFactory();

                    #region Read Tables

                    var tableBuildHelperList = new List<TableBuildHelper>();
                    List<string> failedTableColumns = new List<string>();
                    foreach (var table in schema.Tables)
                    {
                        try
                        {
                            var tableBuildHelper = new TableBuildHelper();
                            tableBuildHelper.Name = table.Name;
                            tableBuildHelper.Properties = new List<TablePropertyBuildHelper>();

                            #region Field properties

                            foreach (var col in table.Columns)
                            {
                                if (col.DataType == null)
                                {
                                    failedTableColumns.Add(string.Format("{0} - {1}", table.Name, col.ToString()));
                                }
                                else
                                {
                                    Type colType = Type.GetType(col.DataType.NetDataType);
                                    if (col.Nullable)
                                    {
                                        if (col.DataType.IsInt)
                                        {
                                            colType = typeof(Nullable<int>);
                                        }
                                        else if (col.DataType.IsDateTime)
                                        {
                                            colType = typeof(Nullable<DateTime>);
                                        }
                                        else if (col.DataType.IsFloat)
                                        {
                                            colType = typeof(Nullable<float>);
                                        }
                                        else if (col.DataType.IsNumeric)
                                        {
                                            colType = typeof(Nullable<decimal>);
                                        }
                                        else if (col.DataType.TypeName == "datetimeoffset")
                                        {
                                            colType = typeof(Nullable<DateTimeOffset>);
                                        }
                                        else if (col.DataType.NetDataTypeCSharpName == "bool")
                                        {
                                            colType = typeof(Nullable<bool>);
                                        }
                                    }

                                    //Sequense logic
                                    string sequenceScript = null;
                                    if (col.IsPrimaryKey && !string.IsNullOrEmpty(col.DefaultValue) && col.DefaultValue.StartsWith("(NEXT VALUE FOR"))
                                        sequenceScript = col.DefaultValue.Substring(1, col.DefaultValue.Length - 2);

                                    FieldPropertyData fieldPropertyData = new FieldPropertyData()
                                    {
                                        IsPrimaryKey = col.IsPrimaryKey,
                                        IsForeignKey = col.IsForeignKey,
                                        Order = table.Columns.IndexOf(col) + 1,
                                        Nullable = col.Nullable,
                                        Type = colType,
                                        MaxLength = col.Length,
                                        IsComputedID = col.IsPrimaryKey && col.IdentityDefinition == null,
                                        SequenceScript = sequenceScript,
                                        ColumnName = col.Name
                                    };

                                    string name = col.Name;
                                    while (table.Name == name || tableBuildHelper.Properties.Exists(p => p.Name == name))
                                        name = name + "1";

                                    var tablePropertyBuildHelper = new TablePropertyBuildHelper();
                                    tablePropertyBuildHelper.Name = name;
                                    tablePropertyBuildHelper.Data = fieldPropertyData;
                                    tableBuildHelper.Properties.Add(tablePropertyBuildHelper);
                                }
                            }

                            #endregion

                            //Make all existing foreign keys as primary key if entity has no primary key
                            if (tableBuildHelper.Properties.FirstOrDefault(x => ((FieldPropertyData)x.Data).IsPrimaryKey) == null)
                            {
                                var foreignRows = tableBuildHelper.Properties.Where(x => (((FieldPropertyData)x.Data).IsForeignKey)).ToList();
                                foreignRows.ForEach(p => ((FieldPropertyData)p.Data).IsPrimaryKey = true);
                            }

                            var tableTypeBuilder = CreateTypeBuilder(dynamicClassFactory, table.Name, null);
                            tableBuildHelper.TypeBuilder = tableTypeBuilder;
                            tableBuildHelperList.Add(tableBuildHelper);
                        }
                        catch (Exception exception)
                        {
                            DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                        }
                    }

                    #region Navigation properties

                    foreach (var table in schema.Tables)
                    {
                        #region Foreign Keys

                        foreach (var foreignKey in table.ForeignKeys)
                        {
                            try
                            {
                                var tableBuildHelper = tableBuildHelperList.Find(table.Name);
                                var columnType = tableBuildHelperList.Find(foreignKey.RefersToTable).TypeBuilder;

                                //Foreign Key property
                                {
                                    ForeignKeyPropertyData foreignKeyPropertyData = new ForeignKeyPropertyData()
                                    {
                                        Type = columnType,
                                        ColumnName = tableBuildHelper.Properties.Find(foreignKey.Columns[0]).Name
                                    };

                                    string propName = foreignKey.RefersToTable;
                                    while (table.Name == propName || tableBuildHelper.Properties.Exists(propName))
                                    {
                                        propName = propName + "1";
                                    }

                                    var tablePropertyBuildHelper = new TablePropertyBuildHelper();
                                    tablePropertyBuildHelper.Name = propName;
                                    tablePropertyBuildHelper.Data = foreignKeyPropertyData;
                                    tableBuildHelper.Properties.Add(tablePropertyBuildHelper);
                                }

                                var fkTableBuildHelper = tableBuildHelperList.Find(foreignKey.RefersToTable);
                                var fkColumnType = typeof(ICollection<>).MakeGenericType(tableBuildHelper.TypeBuilder);

                                //if (table.Name == "BatchProductionRecord") //foreignKey.Columns[0] == "Events")
                                //Inverse property
                                {
                                    InversePropertyData inversePropertyData = new InversePropertyData()
                                    {
                                        Type = fkColumnType,
                                        ColumnName = tableBuildHelper.Properties.Last().Name //propName
                                    };

                                    string propName = foreignKey.TableName;
                                    while (foreignKey.RefersToTable == propName || fkTableBuildHelper.Properties.Exists(propName))
                                    {
                                        propName = propName + "1";
                                    }

                                    var tablePropertyBuildHelper = new TablePropertyBuildHelper();
                                    tablePropertyBuildHelper.Name = propName;
                                    tablePropertyBuildHelper.Data = inversePropertyData;
                                    fkTableBuildHelper.Properties.Add(tablePropertyBuildHelper);
                                }
                            }
                            catch (Exception exception)
                            {
                                DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                            }
                        }

                        #endregion
                    }

                    #endregion

                    #region Create properties and table types from type builder and add to DB model

                    foreach (var table in tableBuildHelperList)
                    {
                        foreach (var property in table.Properties)
                        {
                            try
                            {
                                dynamicClassFactory.CreateProperty(table.TypeBuilder, new KeyValuePair<string, DynamicPropertyData>(property.Name, property.Data), null);
                            }
                            catch (Exception exception)
                            {
                                DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                            }
                        }

                        try
                        {
                            var tableType = table.TypeBuilder.CreateType();
                            var entity = modelBuilder.Entity(tableType);
                        }
                        catch (Exception exception)
                        {
                            DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                        }
                    }

                    #endregion

                    #endregion

                    #region Read Views

                    List<string> failedViewColumns = new List<string>();
                    foreach (var view in schema.Views)
                    {
                        try
                        {
                            AddViewToModel(modelBuilder, dynamicClassFactory, failedViewColumns, view);
                        }
                        catch (Exception exception)
                        {
                            DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                        }
                    }

                    #endregion

                    #region Read Actions

                    AddActionsToModel(modelBuilder, schema, dynamicClassFactory);

                    #endregion
                }

                #endregion

                #region Add Metadata object for user rules custom metadata

                try
                {
                    var metadataObject = modelBuilder.Entity<DynamicMetadataObject>();
                    metadataObject.HasKey(a => a.Name);
                    metadataObject.Property(a => a.Type);
                    metadataObject.Property(a => a.Schema);
                }
                catch (Exception exception)
                {
                    DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                }

                #endregion

                #region Add service info object to model

                try
                {
                    var serviceInfoObject = modelBuilder.Entity<DynamicServiceInfoObject>();
                    serviceInfoObject.HasKey(a => a.IISVersion);
                    serviceInfoObject.Property(a => a.TargetFramework);
                    serviceInfoObject.Property(a => a.AppDomainAppPath);
                    serviceInfoObject.Property(a => a.AssemblyDictionary);
                }
                catch (Exception exception)
                {
                    DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                }

                #endregion

                var databaseModel = modelBuilder.Build(new System.Data.SqlClient.SqlConnection(cConnectionStringSettings.ConnectionString));
                compiledDatabaseModel = databaseModel.Compile();
            }
            catch (Exception exception)
            {
                DynamicLogger.Instance.WriteLoggerLogError("CreateModel", exception);
                throw exception;
            }

            return compiledDatabaseModel;
        }
        /// <summary>	Adds a view to model. </summary>
        ///
        /// <param name="modelBuilder">		  	The builder that defines the model for the context being
        /// 									created. </param>
        /// <param name="dynamicClassFactory">	The dynamic class factory. </param>
        /// <param name="failedViewColumns">  	The failed view columns. </param>
        /// <param name="view">				  	The view. </param>
        ///
        /// <returns>	A Type. </returns>
        private static Type AddViewToModel(
            DbModelBuilder modelBuilder,
            DynamicClassFactory dynamicClassFactory,
            List<string> failedViewColumns,
            DatabaseView view)
        {
            var property = new Dictionary<string, DynamicPropertyData>();
            foreach (var col in view.Columns)
            {
                if (col.DataType == null)
                {
                    failedViewColumns.Add(string.Format("{0} - {1}", view.Name, col.ToString()));
                }
                else
                {
                    Type colType = Type.GetType(col.DataType.NetDataType);
                    if (col.Nullable)
                    {
                        if (col.DataType.IsInt)
                        {
                            colType = typeof(Nullable<int>);
                        }
                        else if (col.DataType.IsDateTime)
                        {
                            colType = typeof(Nullable<DateTime>);
                        }
                        else if (col.DataType.IsFloat)
                        {
                            colType = typeof(Nullable<float>);
                        }
                        else if (col.DataType.IsNumeric)
                        {
                            colType = typeof(Nullable<decimal>);
                        }
                        else if (col.DataType.TypeName == "datetimeoffset")
                        {
                            colType = typeof(Nullable<DateTimeOffset>);
                        }
                        else if (col.DataType.NetDataTypeCSharpName == "bool")
                        {
                            colType = typeof(Nullable<bool>);
                        }
                    }
                    DynamicPropertyData dynamicPropertyData = new FieldPropertyData()
                    {
                        IsPrimaryKey = col.IsPrimaryKey,
                        IsForeignKey = col.IsForeignKey,
                        Order = view.Columns.IndexOf(col) + 1,
                        Nullable = col.Nullable,
                        Type = colType,
                        MaxLength = col.Length,
                        ColumnName = col.Name
                    };

                    string name = col.Name;
                    while (property.ContainsKey(name) || view.Name == name)
                    {
                        name = name + "1";
                    }
                    property.Add(name, dynamicPropertyData);
                }
            }

            //Make all existing foreign keys as primary key if entity has no primary key
            if (property.Values.FirstOrDefault(x => ((FieldPropertyData)x).IsPrimaryKey) == null)
            {
                var foreignRows = property.Values.Where(x => (((FieldPropertyData)x).IsForeignKey)).ToList();
                foreignRows.ForEach(p => ((FieldPropertyData)p).IsPrimaryKey = true);
            }

            var viewType = CreateType(dynamicClassFactory, view.Name, property);
            var entity = modelBuilder.Entity(viewType);
            var methodInfoMap = entity.TypeConfiguration.GetType().GetMethod("MapToStoredProcedures", new Type[] { });
            methodInfoMap.Invoke(entity.TypeConfiguration, new object[] { });

            return viewType;
        }