public virtual IModel CreateModel() { // the relationalModel is an IModel, but not the one that will be returned // it's just directly from the database - EntityType = table, Property = column // etc with no attempt to hook up foreign key columns or make the // names fit CSharp conventions etc. var relationalModel = ConstructRelationalModel(); var nameMapper = new SqlServerNameMapper( relationalModel, entity => _tables[entity.Name].TableName, property => _tableColumns[property.Name].ColumnName); return ConstructCodeGenModel(relationalModel, nameMapper); }
public virtual IModel ConstructCodeGenModel( [NotNull] IModel relationalModel, [NotNull] SqlServerNameMapper nameMapper) { Check.NotNull(relationalModel, nameof(relationalModel)); Check.NotNull(nameMapper, nameof(nameMapper)); var codeGenModel = new Microsoft.Data.Entity.Metadata.Model(); foreach (var relationalEntityType in relationalModel.EntityTypes.Cast<EntityType>()) { var codeGenEntityType = codeGenModel .AddEntityType(nameMapper.EntityTypeToClassNameMap[relationalEntityType]); _relationalEntityTypeToCodeGenEntityTypeMap[relationalEntityType] = codeGenEntityType; codeGenEntityType.Relational().Table = _tables[relationalEntityType.Name].TableName; codeGenEntityType.Relational().Schema = _tables[relationalEntityType.Name].SchemaName; // Loop over relational properties constructing a matching property in the // codeGenModel. Also accumulate: // a) primary key properties // b) constraint properties var primaryKeyProperties = new List<Property>(); var constraints = new Dictionary<string, List<Property>>(); _relationalEntityTypeToForeignKeyConstraintsMap[relationalEntityType] = constraints; foreach (var relationalProperty in relationalEntityType.Properties) { int primaryKeyOrdinal; if (_primaryKeyOrdinals.TryGetValue(relationalProperty.Name, out primaryKeyOrdinal)) { // add _relational_ property so we can order on the ordinal later primaryKeyProperties.Add(relationalProperty); } Dictionary<string, int> foreignKeyConstraintIdOrdinalMap; if (_foreignKeyOrdinals.TryGetValue(relationalProperty.Name, out foreignKeyConstraintIdOrdinalMap)) { // relationalProperty represents (part of) a foreign key foreach (var constraintId in foreignKeyConstraintIdOrdinalMap.Keys) { List<Property> constraintProperties; if (!constraints.TryGetValue(constraintId, out constraintProperties)) { constraintProperties = new List<Property>(); constraints.Add(constraintId, constraintProperties); } constraintProperties.Add(relationalProperty); } } var codeGenProperty = codeGenEntityType.AddProperty( nameMapper.PropertyToPropertyNameMap[relationalProperty], relationalProperty.ClrType, shadowProperty: true); _relationalPropertyToCodeGenPropertyMap[relationalProperty] = codeGenProperty; ApplyPropertyProperties(codeGenProperty, _tableColumns[relationalProperty.Name]); } // end of loop over all relational properties for given EntityType if (primaryKeyProperties.Count() > 0) { // order the relational properties by their primaryKeyOrdinal, then return a list // of the codeGen properties mapped to each relational property in that order codeGenEntityType.SetPrimaryKey( primaryKeyProperties .OrderBy(p => _primaryKeyOrdinals[p.Name]) // note: for relational property p.Name is its columnId .Select(p => _relationalPropertyToCodeGenPropertyMap[p]) .ToList()); } else { var errorMessage = Strings.NoPrimaryKeyColumns( codeGenEntityType.Name, _tables[relationalEntityType.Name].SchemaName, _tables[relationalEntityType.Name].TableName); codeGenEntityType.AddAnnotation(AnnotationNameEntityTypeError, errorMessage); _logger.LogWarning(Strings.CannotGenerateEntityType(codeGenEntityType.Name, errorMessage)); } } // end of loop over all relational EntityTypes AddForeignKeysToCodeGenModel(codeGenModel); return codeGenModel; }