diff --git a/DotnetEfDbcontextConverter/DotnetEfDbcontextConverter.csproj b/DotnetEfDbcontextConverter/DotnetEfDbcontextConverter.csproj index c73e0d1..e0aecaa 100644 --- a/DotnetEfDbcontextConverter/DotnetEfDbcontextConverter.csproj +++ b/DotnetEfDbcontextConverter/DotnetEfDbcontextConverter.csproj @@ -1,8 +1,9 @@ - - Exe - netcoreapp3.1 - + + Exe + net6.0 + LatestMajor + diff --git a/DotnetEfDbcontextConverter/Program.cs b/DotnetEfDbcontextConverter/Program.cs index c373166..90a7d33 100644 --- a/DotnetEfDbcontextConverter/Program.cs +++ b/DotnetEfDbcontextConverter/Program.cs @@ -1,94 +1,125 @@ using System; using System.IO; using System.Linq; +using System.Text; -namespace DotnetEfDbcontextConverter +namespace DotnetEfDbcontextConverter; + +internal class Program { - class Program + private static void Main(string[] args) { - static void Main(string[] args) + if (args.Length == 0) { - if (args.Length == 0) - { - Console.WriteLine( - "Optimizes generated DbContext output of \"dotnet ef dbcontext scaffold\"." + Environment.NewLine + - " - Makes DB schema changeable at runtime" + Environment.NewLine + - " - Removes OnConfiguring method (including connectionString), so you can implement your own partial OnConfiguring method outside the generated context." + Environment.NewLine + - " - Optional parameter --winforms optimizes all generated .cs files in the context file's folder for usage in Windows Forms (grids etc)." + Environment.NewLine + - " - Optional parameter --no-schema does not include the static variable Schema" + Environment.NewLine + - Environment.NewLine + - "Usage: " + Environment.NewLine + - "DotnetEfDbcontextConverter.exe path\\myDbContext.cs [--winforms] [--no-schema]"); - - Console.ReadKey(); - - return; - } + Console.WriteLine( + "Optimizes generated DbContext output of \"dotnet ef dbcontext scaffold\"." + Environment.NewLine + + " - Makes DB schema changeable at runtime" + Environment.NewLine + + " - Removes OnConfiguring method (including connectionString), so you can implement your own partial OnConfiguring method outside the generated context." + + Environment.NewLine + + " - Optional parameter --winforms optimizes all generated .cs files in the context file's folder for usage in Windows Forms (grids etc)." + + Environment.NewLine + + " - Optional parameter --no-schema does not include the static variable Schema" + Environment.NewLine + + " - Optional parameter --internal-only makes all model files and the context internal. This is meant for projects with e.g. an sqlite datasource." + + Environment.NewLine + + Environment.NewLine + + "Usage: " + Environment.NewLine + + "DotnetEfDbcontextConverter.exe path\\myDbContext.cs [--winforms] [--no-schema] [--internal-only]"); - - string file = args[0]; - - String content = File.ReadAllText(file); - File.Copy(file, file + ".backup", true); - - Console.WriteLine("Backup file generated."); - - //Get original schema name - var addSchema = !args.Any(a => a == "--no-schema"); - var lines = content.Split(Environment.NewLine).ToList(); - - if (addSchema) { - var schemaPosition = content.IndexOf("entity.ToTable("); - var origSchema = content.Substring(schemaPosition, 50); - try { - origSchema = origSchema.Split(",")[1].Trim().Trim('"'); - var schemaEndPosition = origSchema.IndexOf('"'); - origSchema = origSchema.Substring(0, schemaEndPosition); - } catch (IndexOutOfRangeException) //As an alternative method, use database name from connection string - { - schemaPosition = content.IndexOf("database="); - if (schemaPosition != -1) { - origSchema = content.Substring(schemaPosition); - origSchema = origSchema.Split(";", 2)[0].Trim().Replace("database=", "").Replace("\"", "").Replace(")", ""); - } else // not found; connection string could possibly be anything except a RDBMS (e.g. SQLite-Datasource, ...) - origSchema = ""; - } + Console.ReadKey(); - //Insert static schema variable declaration - var staticVarDecl = Environment.NewLine + "\t\tpublic static string Schema = \"" + origSchema + "\";" + Environment.NewLine + Environment.NewLine; - if (!content.Contains(staticVarDecl) && origSchema != "") { - var staticVarPosition = content.IndexOf(": DbContext") + 20; - content = content.Insert(staticVarPosition, staticVarDecl); - } + return; + } - //Replace hard-coded schema name with variable - lines = lines.Select(line => - line.Contains("entity.ToTable") && addSchema - ? line.Replace($"\"{ origSchema }\"", "Schema") - : line - ).ToList(); + + var file = args[0]; + + var content = File.ReadAllText(file); + File.Copy(file, file + ".backup", true); + + Console.WriteLine("Backup file generated."); + + //Get original schema name + var addSchema = args.All(a => a != "--no-schema"); + var lines = content.Split(Environment.NewLine).ToList(); + + if (addSchema) + { + var schemaPosition = content.IndexOf("entity.ToTable(", StringComparison.Ordinal); + var origSchema = content.Substring(schemaPosition, 50); + try + { + origSchema = origSchema.Split(",")[1].Trim().Trim('"'); + var schemaEndPosition = origSchema.IndexOf('"'); + origSchema = origSchema[..schemaEndPosition]; } - //Remove OnConfiguring method - var onConfigStartpos = lines.FindIndex(o => o.Contains("protected override void OnConfiguring")); - lines.RemoveRange(onConfigStartpos, 8); - - //For better WinForms / grid usage: Replace ICollection and HashSet with BindingList - //(E.g. using parent/child relations in grid, ICollection might have only 2 grid columns like "Count" or "ReadOnly" - //Alternative (untested): Use context.table.ToBindingList() as DataSource as described here: https://blogs.msdn.microsoft.com/efdesign/2010/09/08/data-binding-with-dbcontext/ - if (args.Any(a => a == "--winforms")) + catch (IndexOutOfRangeException) //As an alternative method, use database name from connection string { - var dir = new FileInfo(file).DirectoryName; - foreach (var f in Directory.GetFiles(dir, "*.cs")) + schemaPosition = content.IndexOf("database=", StringComparison.Ordinal); + if (schemaPosition != -1) + { + origSchema = content[schemaPosition..]; + origSchema = origSchema.Split(";", 2)[0].Trim().Replace("database=", "").Replace("\"", "") + .Replace(")", ""); + } + else // not found; connection string could possibly be anything except a RDBMS (e.g. SQLite-Datasource, ...) { - var fcontent = File.ReadAllText(f); - fcontent = "using System.ComponentModel;" + Environment.NewLine + fcontent.Replace("ICollection<", "IList<").Replace("HashSet<", "BindingList<"); - File.WriteAllText(f, fcontent, System.Text.Encoding.Default); + origSchema = ""; } } - File.WriteAllLines(file, lines, System.Text.Encoding.Default); + //Insert static schema variable declaration + var staticVarDecl = Environment.NewLine + "\t\tpublic static string Schema = \"" + origSchema + "\";" + + Environment.NewLine + Environment.NewLine; + if (!content.Contains(staticVarDecl) && origSchema != "") + { + var staticVarPosition = content.IndexOf(": DbContext", StringComparison.Ordinal) + 20; + content = content.Insert(staticVarPosition, staticVarDecl); + } + + //Replace hard-coded schema name with variable + lines = lines.Select(line => + line.Contains("entity.ToTable") && addSchema + ? line.Replace($"\"{origSchema}\"", "Schema") + : line + ).ToList(); + } + + //Remove OnConfiguring method + var onConfigStartpos = lines.FindIndex(o => o.Contains("protected override void OnConfiguring")); + lines.RemoveRange(onConfigStartpos, 8); - Console.WriteLine("Converting finished."); + File.WriteAllLines(file, lines, Encoding.Default); + + //For better WinForms / grid usage: Replace ICollection and HashSet with BindingList + //(E.g. using parent/child relations in grid, ICollection might have only 2 grid columns like "Count" or "ReadOnly" + //Alternative (untested): Use context.table.ToBindingList() as DataSource as described here: https://blogs.msdn.microsoft.com/efdesign/2010/09/08/data-binding-with-dbcontext/ + if (args.Any(a => a == "--winforms")) + { + var dir = new FileInfo(file).DirectoryName; + foreach (var f in Directory.GetFiles(dir, "*.cs")) + { + var fcontent = File.ReadAllText(f); + fcontent = "using System.ComponentModel;" + Environment.NewLine + + fcontent.Replace("ICollection<", "IList<").Replace("HashSet<", "BindingList<"); + File.WriteAllText(f, fcontent, Encoding.Default); + } + } + + if (args.Any(a => a == "--internal-only")) + { + MakeClassesInternal(new FileInfo(file).DirectoryName); + } + + Console.WriteLine("Converting finished."); + } + + static void MakeClassesInternal(string directory) + { + foreach (var file in Directory.GetFiles(directory, "*.cs")) + { + var content = File.ReadAllText(file); + content = content.Replace("public partial class", "internal partial class"); + File.WriteAllText(file, content, Encoding.Default); } } -} +} \ No newline at end of file diff --git a/coreapp-dll.zip b/coreapp-dll.zip index 72f03a9..308b70d 100644 Binary files a/coreapp-dll.zip and b/coreapp-dll.zip differ diff --git a/coreapp-exe.zip b/coreapp-exe.zip index d41375b..169d562 100644 Binary files a/coreapp-exe.zip and b/coreapp-exe.zip differ