/// <summary> /// Creates entity model from table/view schema information. /// </summary> /// <param name="dataContext">Current data model's data context descriptor.</param> /// <param name="table">Table or view schema data.</param> /// <param name="defaultSchemas">List of default database schema names.</param> /// <param name="baseType">Optional base entity class type.</param> private void BuildEntity( DataContextModel dataContext, TableLikeObject table, ISet <string> defaultSchemas, IType?baseType) { var(tableName, isNonDefaultSchema) = ProcessObjectName(table.Name, defaultSchemas); var metadata = new EntityMetadata() { Name = tableName, IsView = table is View }; // generate name for entity table property in data context class var contextPropertyName = _options.DataModel.EntityContextPropertyNameProvider?.Invoke(table); contextPropertyName = contextPropertyName != null ? contextPropertyName : _namingServices.NormalizeIdentifier( _options.DataModel.EntityContextPropertyNameOptions, table.Name.Name); // generate entity class name var className = _options.DataModel.EntityClassNameProvider?.Invoke(table); var hasCustomClassName = className != null; className = className != null ? className : _namingServices.NormalizeIdentifier( _options.DataModel.EntityClassNameOptions, table.Name.Name); // add schema name ato entity class name as prefix for table from non-default schema without // class-per-schema option set if (!hasCustomClassName && !_options.DataModel.GenerateSchemaAsType && isNonDefaultSchema) { className = table.Name.Schema + "_" + className; } // entity class properties var classModel = new ClassModel(_options.CodeGeneration.ClassPerFile ? className : dataContext.Class.FileName !, className); classModel.Summary = table.Description; classModel.BaseType = baseType; classModel.Namespace = _options.CodeGeneration.Namespace; classModel.Modifiers = Modifiers.Public; if (_options.DataModel.EntityClassIsPartial) { classModel.Modifiers = classModel.Modifiers | Modifiers.Partial; } // entity data model var entity = new EntityModel( metadata, classModel, contextPropertyName == null ? null // note that property type is open-generic here // concrete type argument will be set later during AST generation : new PropertyModel(contextPropertyName, WellKnownTypes.LinqToDB.ITableT) { Modifiers = Modifiers.Public, Summary = table.Description }); entity.ImplementsIEquatable = _options.DataModel.GenerateIEquatable; entity.FindExtensions = _options.DataModel.GenerateFindExtensions; // add entity to lookup _entities.Add(table.Name, new TableWithEntity(table, entity)); BuildEntityColumns(table, entity); // call interceptor after entity model completely configured _interceptors.PreprocessEntity(_languageProvider.TypeParser, entity); // add entity to model if (isNonDefaultSchema && _options.DataModel.GenerateSchemaAsType) { GetOrAddAdditionalSchema(dataContext, table.Name.Schema !).Entities.Add(entity); } else { dataContext.Entities.Add(entity); } }
/// <summary> /// Converts schema's table/view columns, primary key and identity information to entity columns. /// </summary> /// <param name="table">Table/view schema object.</param> /// <param name="entity">Entity.</param> private void BuildEntityColumns(TableLikeObject table, EntityModel entity) { Dictionary <string, ColumnModel> entityColumnsMap; _columns.Add(entity, entityColumnsMap = new()); foreach (var column in table.Columns) { var typeMapping = MapType(column.Type); var columnMetadata = new ColumnMetadata() { Name = column.Name }; var propertyName = _namingServices.NormalizeIdentifier( _options.DataModel.EntityColumnPropertyNameOptions, column.Name); var propertyType = typeMapping.CLRType.WithNullability(column.Nullable); var columnProperty = new PropertyModel(propertyName, propertyType) { Modifiers = Modifiers.Public, IsDefault = true, HasSetter = true, Summary = column.Description, TrailingComment = column.Type.Name }; var columnModel = new ColumnModel(columnMetadata, columnProperty); entity.Columns.Add(columnModel); entityColumnsMap.Add(column.Name, columnModel); // populate metadata for column columnMetadata.DbType = column.Type; if (!_options.DataModel.GenerateDbType) { columnMetadata.DbType = columnMetadata.DbType with { Name = null } } ; if (!_options.DataModel.GenerateLength) { columnMetadata.DbType = columnMetadata.DbType with { Length = null } } ; if (!_options.DataModel.GeneratePrecision) { columnMetadata.DbType = columnMetadata.DbType with { Precision = null } } ; if (!_options.DataModel.GenerateScale) { columnMetadata.DbType = columnMetadata.DbType with { Scale = null } } ; if (_options.DataModel.GenerateDataType) { columnMetadata.DataType = typeMapping.DataType; } columnMetadata.CanBeNull = column.Nullable; columnMetadata.SkipOnInsert = !column.Insertable; columnMetadata.SkipOnUpdate = !column.Updatable; columnMetadata.IsIdentity = table.Identity != null && table.Identity.Column == column.Name; if (table.PrimaryKey != null) { columnMetadata.IsPrimaryKey = table.PrimaryKey.Columns.Contains(column.Name); if (columnMetadata.IsPrimaryKey && table.PrimaryKey.Columns.Count > 1) { columnMetadata.PrimaryKeyOrder = table.PrimaryKey.GetColumnPositionInKey(column); } } } }