/// <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; }