diff --git a/src/EntityFrameworkCore.Generator.Core/CodeGenerator.cs b/src/EntityFrameworkCore.Generator.Core/CodeGenerator.cs index 89eaa6a2..186e47c6 100644 --- a/src/EntityFrameworkCore.Generator.Core/CodeGenerator.cs +++ b/src/EntityFrameworkCore.Generator.Core/CodeGenerator.cs @@ -90,6 +90,9 @@ private void GenerateQueryExtensions(EntityContext entityContext) private void GenerateMappingClasses(EntityContext entityContext) { + if (Options.Data.Mapping.DeleteUnusedFiles) + DeleteUnusedFiles(Options.Data.Mapping.Directory, entityContext.Entities.Select(e => e.MappingClass).ToHashSet(), "mapping"); + foreach (var entity in entityContext.Entities) { Options.Variables.Set(entity); @@ -111,6 +114,9 @@ private void GenerateMappingClasses(EntityContext entityContext) private void GenerateEntityClasses(EntityContext entityContext) { + if (Options.Data.Entity.DeleteUnusedFiles) + DeleteUnusedFiles(Options.Data.Entity.Directory, entityContext.Entities.Select(e => e.EntityClass).ToHashSet(), "entity"); + foreach (var entity in entityContext.Entities) { Options.Variables.Set(entity); @@ -130,6 +136,20 @@ private void GenerateEntityClasses(EntityContext entityContext) } } + private void DeleteUnusedFiles(string directory, HashSet fileNamesToBeGenerated, string fileType) + { + var existingFiles = Directory.EnumerateFiles(directory, "*.cs"); + foreach (var existingFile in existingFiles) + { + var fileName = Path.GetFileNameWithoutExtension(existingFile); + if (!fileNamesToBeGenerated.Contains(fileName)) + { + _logger.LogInformation("Deleting {fileType} class: {file}.cs", fileType, fileName); + File.Delete(existingFile); + } + } + } + private void GenerateDataContext(EntityContext entityContext) { diff --git a/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs b/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs index ad837307..5efebf78 100644 --- a/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs +++ b/src/EntityFrameworkCore.Generator.Core/OptionMapper.cs @@ -145,6 +145,7 @@ private static void MapMapping(MappingClassOptions option, MappingClass mapping) option.Temporal = mapping.Temporal; option.RowVersion = mapping.RowVersion; + option.DeleteUnusedFiles = mapping.DeleteUnusedFiles; } private static void MapEntity(EntityClassOptions option, EntityClass entity) @@ -154,6 +155,7 @@ private static void MapEntity(EntityClassOptions option, EntityClass entity) option.EntityNaming = entity.EntityNaming; option.RelationshipNaming = entity.RelationshipNaming; option.PrefixWithSchemaName = entity.PrefixWithSchemaName; + option.DeleteUnusedFiles = entity.DeleteUnusedFiles; MapSelection(option.Renaming, entity.Renaming); } diff --git a/src/EntityFrameworkCore.Generator.Core/Options/EntityClassOptions.cs b/src/EntityFrameworkCore.Generator.Core/Options/EntityClassOptions.cs index bcd70548..1354b29d 100644 --- a/src/EntityFrameworkCore.Generator.Core/Options/EntityClassOptions.cs +++ b/src/EntityFrameworkCore.Generator.Core/Options/EntityClassOptions.cs @@ -55,4 +55,10 @@ public EntityClassOptions(VariableDictionary variables, string prefix) /// The renaming expressions. /// public SelectionOptions Renaming { get; } + + /// + /// If true, files without a corresponding database table will be removed in the folder + /// + [DefaultValue(false)] + public bool DeleteUnusedFiles { get; set; } } diff --git a/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs b/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs index c5ad6fc1..ecafaa97 100644 --- a/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs +++ b/src/EntityFrameworkCore.Generator.Core/Options/MappingClassOptions.cs @@ -38,4 +38,9 @@ public MappingClassOptions(VariableDictionary variables, string prefix) [DefaultValue(RowVersionMapping.ByteArray)] public RowVersionMapping RowVersion { get; set; } = RowVersionMapping.ByteArray; + /// + /// If true, files without a corresponding database table will be removed in the folder + /// + [DefaultValue(false)] + public bool DeleteUnusedFiles { get; set; } } diff --git a/src/EntityFrameworkCore.Generator.Core/Serialization/EntityClass.cs b/src/EntityFrameworkCore.Generator.Core/Serialization/EntityClass.cs index 1ca37afb..a14fed7a 100644 --- a/src/EntityFrameworkCore.Generator.Core/Serialization/EntityClass.cs +++ b/src/EntityFrameworkCore.Generator.Core/Serialization/EntityClass.cs @@ -54,4 +54,10 @@ public EntityClass() /// The renaming expressions. /// public SelectionModel Renaming { get; set; } + + /// + /// If true, files without a corresponding database table will be removed in the folder + /// + [DefaultValue(false)] + public bool DeleteUnusedFiles { get; set; } } diff --git a/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs b/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs index b5c4706a..ecd84873 100644 --- a/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs +++ b/src/EntityFrameworkCore.Generator.Core/Serialization/MappingClass.cs @@ -38,4 +38,10 @@ public MappingClass() [DefaultValue(RowVersionMapping.ByteArray)] public RowVersionMapping RowVersion { get; set; } = RowVersionMapping.ByteArray; + /// + /// If true, files without a corresponding database table will be removed in the folder + /// + [DefaultValue(false)] + public bool DeleteUnusedFiles { get; set; } + } diff --git a/test/EntityFrameworkCore.Generator.Core.Tests/Options/full.yaml b/test/EntityFrameworkCore.Generator.Core.Tests/Options/full.yaml index 5d253569..7347bf10 100644 --- a/test/EntityFrameworkCore.Generator.Core.Tests/Options/full.yaml +++ b/test/EntityFrameworkCore.Generator.Core.Tests/Options/full.yaml @@ -34,6 +34,7 @@ data: relationshipNaming: Plural document: false prefixWithSchemaName: false + deleteUnusedFiles: false renaming: entities: - ^(sp|tbl|udf|vw)_ @@ -43,6 +44,7 @@ data: namespace: '{Project.Namespace}.Data.Mapping' directory: '{Project.Directory}\Data\Mapping' document: false + deleteUnusedFiles: false query: generate: true indexPrefix: By