예제 #1
0
        public static string Generate(IDbConnection connection, string tableSchema, string table, string module, string connectionKey, string entityClass, string permission,
                                      GeneratorConfig config)
        {
            var model = GenerateModel(connection, tableSchema, table, module, connectionKey, entityClass, permission, config);

            return(Templates.Render(GeneratorConfig.GetEntityRowView(config), model));
        }
예제 #2
0
        public MainWindow()
        {
            InitializeComponent();

            var loadProviderDLLs = (ConfigurationManager.AppSettings["LoadProviderDLLs"] ?? "")
                .Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var dll in loadProviderDLLs)
                try
                {
                    Assembly.LoadFrom(dll);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Can't load: " + dll + "\n" + ex.ToString());
                }

            _connections = new BindingList<GeneratorConfig.Connection>();
            _tables = new BindingList<string>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            this.config = GeneratorConfig.Load();

            foreach (var connection in config.Connections)
                _connections.Add(connection);

            if (!config.WebProjectFile.IsEmptyOrNull())
                config.UpdateConnectionsFrom(GetWebConfigLocation(), x => _connections.Add(x));
        }
예제 #3
0
        public EntityCodeGenerator(EntityModel model, GeneratorConfig config, string csproj)
        {
            this.model  = model;
            this.csproj = csproj;

            this.rootDir = Path.GetDirectoryName(csproj);
            this.config  = config;
            this.model.CustomSettings = config.CustomSettings;

            var serverTypings = Path.Combine(rootDir, "Modules/Common/Imports/ServerTypings/"
                                             .Replace('/', Path.DirectorySeparatorChar));

            if (!Directory.Exists(serverTypings))
            {
                serverTypings = Path.Combine(rootDir, "Imports/ServerTypings/".Replace('/', Path.DirectorySeparatorChar));
            }

            serverTypingsTT = (serverTypings.Substring(rootDir.Length + 1) + "ServerTypings.tt").Replace('/', '\\');

            typingClass = Path.Combine(serverTypings, model.ModuleDot + model.ClassName);

            var modulePath = Path.Combine(rootDir, "Modules");

            if (!string.IsNullOrEmpty(model.Module))
            {
                modulePath = Path.Combine(modulePath, model.Module);
            }

            moduleClass = Path.Combine(modulePath, Path.Combine(model.ClassName, model.ClassName));
        }
예제 #4
0
        public EntityCodeGenerator(EntityCodeGenerationModel model, GeneratorConfig config)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path,
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "KDiff3\\kdiff3.exe"),
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "KDiff3\\kdiff3.exe"),
            };

            this.model = model;
            CodeFileHelper.Kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);

            if (config.TFSIntegration)
                CodeFileHelper.SetupTFSIntegration(config.TFPath);

            CodeFileHelper.SetupTSCPath(config.TSCPath);

            siteWebProj = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.WebProjectFile));
            siteWebPath = Path.GetDirectoryName(siteWebProj);
            if (!string.IsNullOrEmpty(config.ScriptProjectFile))
            {
                scriptProject = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.ScriptProjectFile));
                scriptPath = Path.GetDirectoryName(scriptProject);

                if (!File.Exists(scriptProject))
                {
                    scriptProject = null;
                    scriptPath = null;
                }
            }

            this.config = config;
        }
예제 #5
0
        public void Run(string csproj, List <ExternalType> tsTypes)
        {
            var projectDir = Path.GetDirectoryName(csproj);
            var config     = GeneratorConfig.LoadFromFile(Path.Combine(projectDir, "sergen.json"));

            config.ClientTypes = config.ClientTypes ?? new GeneratorConfig.ClientTypesConfig();

            if (config.RootNamespace.IsEmptyOrNull())
            {
                config.RootNamespace = config.GetRootNamespaceFor(csproj);
            }

            var outDir = Path.Combine(projectDir, (config.ClientTypes.OutDir.TrimToNull() ?? "Imports/ClientTypes")
                                      .Replace('/', Path.DirectorySeparatorChar));

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write("Transforming ClientTypes at: ");
            Console.ResetColor();
            Console.WriteLine(outDir);

            var generator = new ClientTypesGenerator();

            generator.RootNamespaces.Add(config.RootNamespace);

            foreach (var type in tsTypes)
            {
                generator.AddTSType(type);
            }

            var codeByFilename = generator.Run();

            new MultipleOutputHelper().WriteFiles(outDir, codeByFilename, "*.ts");
        }
예제 #6
0
        public EntityCodeGenerator(EntityCodeGenerationModel model, GeneratorConfig config)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path,
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "KDiff3\\kdiff3.exe"),
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "KDiff3\\kdiff3.exe"),
            };

            this.model = model;
            CodeFileHelper.Kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);

            if (config.TFSIntegration)
            {
                CodeFileHelper.SetupTFSIntegration(config.TFPath);
            }

            CodeFileHelper.SetupTSCPath(config.TSCPath);

            siteWebProj = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.WebProjectFile));
            siteWebPath = Path.GetDirectoryName(siteWebProj);
            if (!string.IsNullOrEmpty(config.ScriptProjectFile))
            {
                scriptProject = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.ScriptProjectFile));
                scriptPath    = Path.GetDirectoryName(scriptProject);

                if (!File.Exists(scriptProject))
                {
                    scriptProject = null;
                    scriptPath    = null;
                }
            }

            this.config = config;
        }
예제 #7
0
        public MainWindow()
        {
            InitializeComponent();

            _connections = new BindingList <GeneratorConfig.Connection>();
            _tables      = new BindingList <string>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            var configFilePath = GetConfigurationFilePath();

            config                     = JsonConfigHelper.LoadConfig <GeneratorConfig>(configFilePath);
            config.Connections         = config.Connections ?? new List <GeneratorConfig.Connection>();
            config.RemoveForeignFields = config.RemoveForeignFields ?? new List <string>();

            foreach (var connection in config.Connections)
            {
                _connections.Add(connection);
            }

            if (!config.WebProjectFile.IsEmptyOrNull())
            {
                var webConfig = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.WebProjectFile))), "web.config");
                AddConnectionsFromAppConfig(webConfig);
            }
        }
예제 #8
0
        public EntityCodeGenerator(EntityModel model, GeneratorConfig config, string csproj)
        {
            this.model = model;

            rootDir     = Path.GetDirectoryName(Path.GetFullPath(csproj));
            this.config = config;
            this.model.CustomSettings = config.CustomSettings;

            var serverTypings = PathHelper.ToPath(Path.Combine(rootDir, PathHelper.ToPath("Modules/Common/Imports/ServerTypings/")));

            if (!Directory.Exists(serverTypings))
            {
                serverTypings = Path.Combine(rootDir, PathHelper.ToPath("Imports/ServerTypings/"));
            }

            typingClass = Path.Combine(serverTypings, model.ModuleDot + model.ClassName);

            modulePath = Path.Combine(rootDir, "Modules");
            if (!string.IsNullOrEmpty(model.Module))
            {
                modulePath = Path.Combine(modulePath, model.Module);
            }

            moduleClass = Path.Combine(modulePath, Path.Combine(model.ClassName, model.ClassName));
        }
예제 #9
0
        public void Run(string projectJson, List <ExternalType> tsTypes)
        {
            var root       = Path.GetDirectoryName(projectJson);
            var configFile = Path.Combine(root, "sergen.json");

            if (!File.Exists(configFile))
            {
                System.Console.Error.WriteLine("Can't find sergen.json in current directory!");
                Environment.Exit(1);
            }

            var config = GeneratorConfig.LoadFromJson(File.ReadAllText(configFile));

            if (config.ServerTypings == null)
            {
                System.Console.Error.WriteLine("ServerTypings is not configured in sergen.json file!");
                Environment.Exit(1);
            }

            if (config.ServerTypings.Assemblies.IsEmptyOrNull())
            {
                System.Console.Error.WriteLine("ServerTypings has no assemblies configured in sergen.json file!");
                Environment.Exit(1);
            }

            if (config.RootNamespace.IsEmptyOrNull())
            {
                System.Console.Error.WriteLine("Please set RootNamespace option in sergen.json file!");
                Environment.Exit(1);
            }

            var outDir = Path.Combine(root, (config.ServerTypings.OutDir.TrimToNull() ?? "Imports/ServerTypings")
                                      .Replace('/', Path.DirectorySeparatorChar));

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write("Transforming ServerTypings at: ");
            Console.ResetColor();
            Console.WriteLine(outDir);

            List <Assembly> assemblies = new List <Assembly>();

            foreach (var assembly in config.ServerTypings.Assemblies)
            {
                assemblies.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(root, assembly)));
            }

            var generator = new ServerTypingsGenerator(assemblies.ToArray());

            generator.RootNamespaces.Add(config.RootNamespace);

            foreach (var type in tsTypes)
            {
                generator.AddTSType(type);
            }

            var codeByFilename = generator.Run();

            new MultipleOutputHelper().WriteFiles(outDir, codeByFilename, "*.ts");
        }
예제 #10
0
 public static RazorGenerator.Templating.RazorTemplateBase GetEntityRowView(GeneratorConfig config)
 {
     RazorGenerator.Templating.RazorTemplateBase entityRow;
     if (config.RowFieldsSurroundWithRegion)
         entityRow = new Views.EntityRowWithRegion();
     else
         entityRow = new Views.EntityRow();
     return entityRow;
 }
예제 #11
0
 private void GenerateRow()
 {
     if (config.RowFieldsSurroundWithRegion)
     {
         CreateNewSiteWebFile(Templates.Render(GeneratorConfig.GetEntityRowView(config), model, config),
                              Path.Combine(@"Modules\", Path.Combine(model.Module ?? model.RootNamespace, Path.Combine(model.ClassName, model.RowClassName + ".cs"))));
     }
     else
     {
         CreateNewSiteWebFile(Templates.Render(GeneratorConfig.GetEntityRowView(config), model),
                              Path.Combine(@"Modules\", Path.Combine(model.Module ?? model.RootNamespace, Path.Combine(model.ClassName, model.RowClassName + ".cs"))));
     }
 }
예제 #12
0
 public static RazorGenerator.Templating.RazorTemplateBase GetEntityRowView(GeneratorConfig config)
 {
     RazorGenerator.Templating.RazorTemplateBase entityRow;
     if (config.RowFieldsSurroundWithRegion)
     {
         entityRow = new Views.EntityRowWithRegion();
     }
     else
     {
         entityRow = new Views.EntityRow();
     }
     return(entityRow);
 }
예제 #13
0
        public EntityCodeGenerator(EntityModel model, GeneratorConfig config, string projectJson)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path
            };

            this.model = model;
            CodeFileHelper.Kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);
            CodeFileHelper.TSCPath    = config.TSCPath ?? "tsc";

            this.rootDir = Path.GetDirectoryName(projectJson);
            this.config  = config;
        }
예제 #14
0
        public static string Generate(IDbConnection connection, string tableSchema, string table, string module, string connectionKey, string entityClass, string permission,
                                      GeneratorConfig config)
        {
            var model = GenerateModel(connection, tableSchema, table, module, connectionKey, entityClass, permission, config);

            if (config.RowFieldsSurroundWithRegion)
            {
                return(Templates.Render(new Views.EntityRowWithRegion(), model, config));
            }
            else
            {
                return(Templates.Render(new Views.EntityRow(), model));
            }
        }
예제 #15
0
        public static void Run(string csproj)
        {
            var projectDir = Path.GetDirectoryName(csproj);
            var config     = GeneratorConfig.LoadFromFile(Path.Combine(projectDir, "sergen.json"));

            config.MVC ??= new GeneratorConfig.MVCConfig();

            var outDir = Path.Combine(projectDir, (config.MVC.OutDir.TrimToNull() ?? "Imports/MVC")
                                      .Replace('/', Path.DirectorySeparatorChar));

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write("Transforming MVC at: ");
            Console.ResetColor();
            Console.WriteLine(outDir);

            string[] stripViewPaths = config.MVC.StripViewPaths ?? new string[] {
                "Modules/",
                "Views/",
                Path.GetFileNameWithoutExtension(csproj) + "/"
            };

            var rootDir         = projectDir + Path.DirectorySeparatorChar;
            var searchViewPaths = (config.MVC.SearchViewPaths ??
                                   new string[] {
                "Modules/",
                "Views/",
                Path.GetFileNameWithoutExtension(csproj) + "/"
            })
                                  .Select(x => Path.Combine(rootDir, x.Replace('/', Path.DirectorySeparatorChar)));

            IEnumerable <string> files = new List <string>();

            foreach (var path in searchViewPaths)
            {
                if (Directory.Exists(path))
                {
                    files = files.Concat(Directory.GetFiles(path, "*.cshtml", SearchOption.AllDirectories));
                }
            }

            string getName(string s)
            {
                var path = s[rootDir.Length..];
                var name = Path.ChangeExtension(path, null).Replace('\\', '/');

                foreach (var strip in stripViewPaths)
                {
                    if (name.StartsWith(strip, StringComparison.OrdinalIgnoreCase))
                    {
                        name = name[strip.Length..];
예제 #16
0
        public EntityCodeGenerator(EntityCodeGenerationModel model, GeneratorConfig config)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path,
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "KDiff3\\kdiff3.exe"),
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "KDiff3\\kdiff3.exe"),
            };

            this.model = model;
            kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);
            siteWebProj = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.WebProjectFile));
            siteWebPath = Path.GetDirectoryName(siteWebProj);
            scriptProject = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.ScriptProjectFile));
            scriptPath = Path.GetDirectoryName(scriptProject);
        }
예제 #17
0
        public EntityCodeGenerator(EntityCodeGenerationModel model, GeneratorConfig config)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path,
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "KDiff3\\kdiff3.exe"),
                Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "KDiff3\\kdiff3.exe"),
            };

            this.model = model;
            CodeFileHelper.Kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);
            siteWebProj   = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.WebProjectFile));
            siteWebPath   = Path.GetDirectoryName(siteWebProj);
            scriptProject = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.ScriptProjectFile));
            scriptPath    = Path.GetDirectoryName(scriptProject);
        }
예제 #18
0
        public EntityCodeGenerator(EntityModel model, GeneratorConfig config, string projectJson)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path
            };

            this.model = model;
            CodeFileHelper.Kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);
            CodeFileHelper.TSCPath = config.TSCPath ?? "tsc";

            this.rootDir = Path.GetDirectoryName(projectJson);
            this.config = config;

            this.serverTypings = Path.Combine(rootDir, "Modules/Common/Imports/ServerTypings/".Replace('/', Path.DirectorySeparatorChar));
            if (!Directory.Exists(serverTypings))
                this.serverTypings = Path.Combine(rootDir, "Imports/ServerTypings/".Replace('/', Path.DirectorySeparatorChar));
        }
예제 #19
0
        public MainWindow()
        {
            InitializeComponent();

            _connections = new BindingList<GeneratorConfig.Connection>();
            _tables = new BindingList<string>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            this.config = GeneratorConfig.Load();

            foreach (var connection in config.Connections)
                _connections.Add(connection);

            if (!config.WebProjectFile.IsEmptyOrNull())
                config.UpdateConnectionsFrom(GetWebConfigLocation(), x => _connections.Add(x));
        }
예제 #20
0
        public void Run(string projectJson, List <ExternalType> tsTypes)
        {
            var root       = Path.GetDirectoryName(projectJson);
            var configFile = Path.Combine(root, "sergen.json");

            if (!File.Exists(configFile))
            {
                System.Console.Error.WriteLine("Can't find sergen.json in current directory!");
                Environment.Exit(1);
            }

            var config = GeneratorConfig.LoadFromJson(File.ReadAllText(configFile));

            config.ClientTypes = config.ClientTypes ?? new GeneratorConfig.ClientTypesConfig();

            if (config.RootNamespace.IsEmptyOrNull())
            {
                System.Console.Error.WriteLine("Please set RootNamespace option in sergen.json file!");
                Environment.Exit(1);
            }

            var outDir = Path.Combine(root, (config.ClientTypes.OutDir.TrimToNull() ?? "Imports/ClientTypes")
                                      .Replace('/', Path.DirectorySeparatorChar));

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.Write("Transforming ClientTypes at: ");
            Console.ResetColor();
            Console.WriteLine(outDir);

            var generator = new ClientTypesGenerator();

            generator.RootNamespaces.Add(config.RootNamespace);

            foreach (var type in tsTypes)
            {
                generator.AddTSType(type);
            }

            var codeByFilename = generator.Run();

            new MultipleOutputHelper().WriteFiles(outDir, codeByFilename, "*.ts");
        }
        public EntityCodeGenerator(EntityModel model, GeneratorConfig config, string csproj)
        {
            var kdiff3Paths = new[]
            {
                config.KDiff3Path
            };

            this.model = model;
            CodeFileHelper.Kdiff3Path = kdiff3Paths.FirstOrDefault(File.Exists);
            CodeFileHelper.TSCPath    = config.TSCPath ?? "tsc";

            this.rootDir = Path.GetDirectoryName(csproj);
            this.config  = config;

            this.serverTypings = Path.Combine(rootDir, "Modules/Common/Imports/ServerTypings/".Replace('/', Path.DirectorySeparatorChar));
            if (!Directory.Exists(serverTypings))
            {
                this.serverTypings = Path.Combine(rootDir, "Imports/ServerTypings/".Replace('/', Path.DirectorySeparatorChar));
            }
        }
예제 #22
0
        private void btnCustomTemplates_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            if (string.IsNullOrWhiteSpace(config.CustomTemplates))
            {
                dlg.FileName         = "*.scriban";
                dlg.InitialDirectory = Path.GetDirectoryName(GeneratorConfig.GetConfigurationFilePath());
            }
            else
            {
                dlg.FileName         = "*.scriban";
                dlg.InitialDirectory = config.CustomTemplates;
            }

            Nullable <bool> result = dlg.ShowDialog();

            if (result == true)
            {
                CustomTemplates = Path.GetDirectoryName(dlg.FileName);
                config.Save();
            }
        }
예제 #23
0
        public MainWindow()
        {
            InitializeComponent();

            _connections = new BindingList <GeneratorConfig.Connection>();
            _tables      = new BindingList <string>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            this.config = GeneratorConfig.Load();

            foreach (var connection in config.Connections)
            {
                _connections.Add(connection);
            }

            if (!config.WebProjectFile.IsEmptyOrNull())
            {
                config.UpdateConnectionsFrom(GetWebConfigLocation(), x => _connections.Add(x));
            }
        }
예제 #24
0
        public static string UnprefixTable(string tableName, string moduleName, GeneratorConfig config)
        {
            if (string.IsNullOrWhiteSpace(tableName) || string.IsNullOrWhiteSpace(moduleName) ||
                config.TablePrefixSettings == null || config.TablePrefixSettings.ModulePrefixes == null ||
                !config.TablePrefixSettings.ModulePrefixes.ContainsKey(moduleName))
            {
                return(tableName);
            }
            else
            {
                var start = config.TablePrefixSettings.ModulePrefixes[moduleName] + "_";

                if (tableName.StartsWith(start, StringComparison.InvariantCultureIgnoreCase))
                {
                    return(tableName.Substring(start.Length));
                }
                else
                {
                    return(tableName);
                }
            }
        }
예제 #25
0
        private void btnTSCPathBrowse_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            if (string.IsNullOrWhiteSpace(config.TSCPath))
            {
                dlg.FileName         = "*.exe";
                dlg.InitialDirectory = Path.GetDirectoryName(GeneratorConfig.GetConfigurationFilePath());
            }
            else
            {
                dlg.FileName         = Path.GetFileName(config.TSCPath);
                dlg.InitialDirectory = Path.GetDirectoryName(config.TSCPath);
            }

            Nullable <bool> result = dlg.ShowDialog();

            if (result == true)
            {
                TSCPath = dlg.FileName;
                config.Save();
            }
        }
예제 #26
0
        private void WebProjectFileBrowse(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            if (string.IsNullOrWhiteSpace(WebProjectFile))
            {
                dlg.FileName         = "*.csproj";
                dlg.InitialDirectory = Path.GetDirectoryName(GeneratorConfig.GetConfigurationFilePath());
            }
            else
            {
                var webProjectFile = Path.GetFullPath(WebProjectFile);
                dlg.FileName         = Path.GetFileName(webProjectFile);
                dlg.InitialDirectory = Path.GetDirectoryName(webProjectFile);
            }

            Nullable <bool> result = dlg.ShowDialog();

            if (result == true)
            {
                WebProjectFile = GeneratorConfig.GetRelativePath(dlg.FileName, AppDomain.CurrentDomain.BaseDirectory);
                config.Save();
            }
        }
예제 #27
0
        public MainWindow()
        {
            InitializeComponent();

            var loadProviderDLLs = (ConfigurationManager.AppSettings["LoadProviderDLLs"] ?? "")
                                   .Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var dll in loadProviderDLLs)
            {
                try
                {
                    Assembly.LoadFrom(dll);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Can't load: " + dll + "\n" + ex.ToString());
                }
            }

            _connections = new BindingList <GeneratorConfig.Connection>();
            _tables      = new BindingList <TableItem>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            this.config = GeneratorConfig.Load();

            foreach (var connection in config.Connections)
            {
                _connections.Add(connection);
            }

            if (!config.WebProjectFile.IsEmptyOrNull())
            {
                config.UpdateConnectionsFrom(GetWebConfigLocation(), x => _connections.Add(x));
            }
        }
예제 #28
0
        public MainWindow()
        {
            InitializeComponent();

            _connections = new BindingList<GeneratorConfig.Connection>();
            _tables = new BindingList<string>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            var configFilePath = GetConfigurationFilePath();
            config = JsonConfigHelper.LoadConfig<GeneratorConfig>(configFilePath);
            config.Connections = config.Connections ?? new List<GeneratorConfig.Connection>();
            config.RemoveForeignFields = config.RemoveForeignFields ?? new List<string>();

            foreach (var connection in config.Connections)
                _connections.Add(connection);

            if (!config.WebProjectFile.IsEmptyOrNull())
            {
                var webConfig = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.WebProjectFile))), "web.config");
                AddConnectionsFromAppConfig(webConfig);
            }
        }
예제 #29
0
        private static EntityField ToEntityField(FieldInfo fieldInfo, int prefixLength, GeneratorConfig config)
        {
            string flags;

            if (fieldInfo.IsIdentity)
            {
                flags = "Identity";
            }
            else if (fieldInfo.IsPrimaryKey)
            {
                flags = "PrimaryKey";
            }
            else if (fieldInfo.DataType == "timestamp" || fieldInfo.DataType == "rowversion")
            {
                flags = "Insertable(false), Updatable(false), NotNull";
            }
            else if (!fieldInfo.IsNullable)
            {
                flags = "NotNull";
            }
            else
            {
                flags = null;
            }

            string dataType;
            var    fieldType = SchemaHelper.SqlTypeNameToFieldType(fieldInfo.DataType, fieldInfo.Size, out dataType);

            dataType = dataType ?? fieldType;
            return(new EntityField
            {
                FieldType = fieldType,
                DataType = dataType,
                IsValueType = fieldType != "String" && fieldType != "Stream" && fieldType != "ByteArray",
                TSType = FieldTypeToTS(fieldType),
                Ident = GenerateVariableName(fieldInfo.FieldName.Substring(prefixLength)),

                //ROLEMBERG FILHO - trata o Tilte de acordo com as regras de AcertaPalavras
                //Title = Inflector.Inflector.Titleize(fieldInfo.FieldName.Substring(prefixLength)),
                Title = config.ReplaceStringinDisplayName ? ToolsHeper.AcertaPalavra(Inflector.Inflector.Titleize(fieldInfo.FieldName.Substring(prefixLength))) :
                        Inflector.Inflector.Titleize(fieldInfo.FieldName.Substring(prefixLength)),
                //ROLEMBERG FILHO - trata o Tilte de acordo com as regras de AcertaPalavras


                Flags = flags,
                Name = fieldInfo.FieldName,
                Size = fieldInfo.Size == 0 ? (Int32?)null : fieldInfo.Size,
                Scale = fieldInfo.Scale
            });
        }
예제 #30
0
        public MainWindow()
        {
            InitializeComponent();

            var loadProviderDLLs = (ConfigurationManager.AppSettings["LoadProviderDLLs"] ?? "")
                                   .Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var dll in loadProviderDLLs)
            {
                try
                {
                    Assembly.LoadFrom(dll);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Can't load: " + dll + "\n" + ex.ToString());
                }
            }

            _connections = new BindingList <GeneratorConfig.Connection>();
            _tables      = new BindingList <TableItem>();

            this.ConnectionsCombo.DataContext = _connections;
            this.DataContext = this;

            this.config = GeneratorConfig.Load();

            foreach (var connection in config.Connections)
            {
                _connections.Add(connection);
            }

            if (!config.WebProjectFile.IsEmptyOrNull())
            {
                config.UpdateConnectionsFrom(GetWebConfigLocation(), x => _connections.Add(x));
            }

            if (!string.IsNullOrEmpty(config.CustomTemplates))
            {
                Templates.TemplatePath = config.CustomTemplates;
            }

            if (config.CustomSettings != null)
            {
                foreach (var pair in config.CustomSettings.OrderBy(x => x.Key))
                {
                    if (pair.Value is Boolean)
                    {
                        var binding = new Binding("CustomSettings[" + pair.Key + "]");
                        binding.Source = this;
                        var checkbox = new CheckBox();
                        checkbox.SetBinding(CheckBox.IsCheckedProperty, binding);
                        checkbox.Content             = Inflector.Inflector.Titleize(pair.Key);
                        checkbox.HorizontalAlignment = HorizontalAlignment.Left;
                        checkbox.Margin = new Thickness(10, 0, 10, 0);
                        checkbox.Click += (s, e) =>
                        {
                            CustomSettings[pair.Key] = checkbox.IsChecked;
                            config.Save();
                        };
                        GenerationOptions.Children.Add(checkbox);
                    }
                    else
                    {
                        var dockPanel = new DockPanel();
                        dockPanel.LastChildFill = true;
                        dockPanel.Margin        = new Thickness(5);
                        var textBlock = new TextBlock();
                        textBlock.Margin = new Thickness(0, 0, 4, 0);
                        textBlock.Width  = 200;
                        textBlock.Text   = Inflector.Inflector.Titleize(pair.Key);
                        dockPanel.Children.Add(textBlock);

                        var binding = new Binding("CustomSettings[" + pair.Key + "]");
                        binding.Source = this;
                        var textbox = new TextBox();
                        textbox.SetBinding(TextBox.TextProperty, binding);
                        textbox.TextChanged += (s, e) =>
                        {
                            CustomSettings[pair.Key] = textbox.Text;
                            config.Save();
                        };
                        dockPanel.Children.Add(textbox);
                        GenerationOptions.Children.Add(dockPanel);
                        DockPanel.SetDock(dockPanel, Dock.Top);
                        DockPanel.SetDock(textBlock, Dock.Left);
                        dockPanel.HorizontalAlignment = HorizontalAlignment.Stretch;
                    }
                }
            }
        }
예제 #31
0
 public void Save()
 {
     Connections.Sort((x, y) => x.Key.CompareTo(y.Key));
     File.WriteAllText(GeneratorConfig.GetConfigurationFilePath(), JSON.StringifyIndented(this));
 }
예제 #32
0
 public void Save()
 {
     Connections.Sort((x, y) => x.Key.CompareTo(y.Key));
     CodeFileHelper.CheckoutAndWrite(GeneratorConfig.GetConfigurationFilePath(),
                                     JSON.StringifyIndented(this), false);
 }
예제 #33
0
        public static EntityModel GenerateModel(IDbConnection connection, string tableSchema, string table,
                                                string module, string connectionKey, string entityClass, string permission, GeneratorConfig config)
        {
            var model = new EntityModel();

            model.Module = module;

            if (connection.GetDialect().ServerType.StartsWith("MySql", StringComparison.OrdinalIgnoreCase))
            {
                model.Schema = null;
            }
            else
            {
                model.Schema = tableSchema;
            }

            model.Permission    = permission;
            model.ConnectionKey = connectionKey;
            model.RootNamespace = config.RootNamespace;
            var className = entityClass ?? ClassNameFromTableName(table);

            model.ClassName                         = className;
            model.RowClassName                      = className + "Row";
            model.Title                             = Inflector.Inflector.Titleize(className);
            model.Tablename                         = table;
            model.Fields                            = new List <EntityField>();
            model.Joins                             = new List <EntityJoin>();
            model.Instance                          = true;
            model.DialogAttributes                  = new DialogAttributes();  /*ROLEMBERG FILHO*/
            model.DialogAttributes.Attrs01          = new List <string>();     /*ROLEMBERG FILHO*/
            model.DialogAttributes.Attrs02          = new List <string>();     /*ROLEMBERG FILHO*/
            model.DialogAttributes.Attrs03          = new List <string>();     /*ROLEMBERG FILHO*/
            model.DialogAttributes.AttrsConstructor = new List <string>();     /*ROLEMBERG FILHO*/
            model.DialogAttributes.AttrsValidacao   = new List <string>();     /*ROLEMBERG FILHO*/
            //model.DialogAttributes.AttrsConfirmSave = new List<string>();      /*ROLEMBERG FILHO*/
            //model.DialogAttributes.Attrs03 = processAdvancedTips_Model(ref model); /*ROLEMBERG FILHO*/
            processAdvancedTips_Model(ref model); /*ROLEMBERG FILHO*/

            var schemaProvider = SchemaHelper.GetSchemaProvider(connection.GetDialect().ServerType);
            var fields         = schemaProvider.GetFieldInfos(connection, tableSchema, table).ToList();

            if (!fields.Any(x => x.IsPrimaryKey))
            {
                var primaryKeys = new HashSet <string>(schemaProvider.GetPrimaryKeyFields(connection, tableSchema, table));
                foreach (var field in fields)
                {
                    field.IsPrimaryKey = primaryKeys.Contains(field.FieldName);
                }
            }

            if (!fields.Any(x => x.IsIdentity))
            {
                var identities = new HashSet <string>(schemaProvider.GetIdentityFields(connection, tableSchema, table));
                foreach (var field in fields)
                {
                    field.IsIdentity = identities.Contains(field.FieldName);
                }
            }

            var foreigns = schemaProvider.GetForeignKeys(connection, tableSchema, table)
                           .ToLookup(x => x.FKName)
                           .Where(x => x.Count() == 1)
                           .SelectMany(x => x)
                           .ToList();

            foreach (var field in fields)
            {
                var fk = foreigns.FirstOrDefault(x => x.FKColumn == field.FieldName);
                if (fk != null)
                {
                    field.PKSchema = fk.PKSchema;
                    field.PKTable  = fk.PKTable;
                    field.PKColumn = fk.PKColumn;
                }
            }

            var prefix = DeterminePrefixLength(fields, x => x.FieldName);

            model.FieldPrefix = fields.First().FieldName.Substring(0, prefix);

            var identity = fields.FirstOrDefault(f => f.IsIdentity == true);

            if (identity == null)
            {
                identity = fields.FirstOrDefault(f => f.IsPrimaryKey == true);
            }
            if (identity != null)
            {
                model.Identity = GenerateVariableName(identity.FieldName.Substring(prefix));
            }
            else
            {
                identity = fields.FirstOrDefault(f => f.IsPrimaryKey == true) ??
                           fields.FirstOrDefault();
                if (identity != null)
                {
                    model.Identity = GenerateVariableName(identity.FieldName.Substring(prefix));
                }
            }

            string           baseRowMatch     = null;
            HashSet <string> baseRowFieldset  = null;
            List <string>    baseRowFieldList = new List <string>();

            foreach (var k in config.BaseRowClasses ?? new List <GeneratorConfig.BaseRowClass>())
            {
                var  b    = k.ClassName;
                var  f    = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                var  fl   = new List <string>();
                bool skip = false;
                foreach (var s in k.Fields ?? new List <string>())
                {
                    string n = s.TrimToNull();
                    if (n == null || !fields.Any(z => z.FieldName.Substring(prefix) == n))
                    {
                        skip = true;
                        break;
                    }
                    f.Add(n);
                    fl.Add(n);
                }

                if (skip)
                {
                    continue;
                }

                if (baseRowFieldset == null || f.Count > baseRowFieldset.Count)
                {
                    baseRowFieldset  = f;
                    baseRowFieldList = fl;
                    baseRowMatch     = b;
                }
            }

            var removeForeignFields = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var s in config.RemoveForeignFields ?? new List <string>())
            {
                string n = s.TrimToNull();
                if (n != null)
                {
                    removeForeignFields.Add(n);
                }
            }

            if (baseRowFieldset != null &&
                baseRowFieldset.Count > 0)
            {
                model.RowBaseClass    = baseRowMatch;
                model.FieldsBaseClass = baseRowMatch + "Fields";
                model.RowBaseFields   = new List <EntityField>();
                fields = fields.Where(f =>
                {
                    if (baseRowFieldset.Contains(f.FieldName.Substring(prefix)))
                    {
                        var ef   = ToEntityField(f, prefix, config);
                        ef.Flags = null;
                        model.RowBaseFields.Add(ef);
                        return(false);
                    }
                    return(true);
                }).ToList();
            }
            else
            {
                model.RowBaseClass    = "Row";
                model.RowBaseFields   = new List <EntityField>();
                model.FieldsBaseClass = "RowFieldsBase";
            }

            var fieldByIdent = new Dictionary <string, EntityField>(StringComparer.OrdinalIgnoreCase);

            foreach (var field in fields)
            {
                var f = ToEntityField(field, prefix, config);

                if (f.Ident == model.IdField)
                {
                    f.ColAttributes = "EditLink, DisplayName(\"Db.Shared.RecordId\"), AlignRight";
                }

                int    i     = 0;
                string ident = f.Ident;
                while (fieldByIdent.ContainsKey(ident))
                {
                    ident = f.Ident + ++i;
                }
                f.Ident             = ident;
                fieldByIdent[ident] = f;

                if (f.Name == className && f.FieldType == "String")
                {
                    model.NameField = f.Name;
                    f.ColAttributes = f.ColAttributes ?? "EditLink";
                }

                //ROLEMBERG FILHO - processa advanced tips para COLUNAS
                f.ColAttributes += processAdvancedTips_Columns(f);
                //ROLEMBERG FILHO - processa advanced tips para COLUNAS

                var foreign = foreigns.Find((k) => k.FKColumn.Equals(field.FieldName, StringComparison.OrdinalIgnoreCase));
                if (foreign != null)
                {
                    if (f.Title.EndsWith(" Id") && f.Title.Length > 3)
                    {
                        f.Title = f.Title.SafeSubstring(0, f.Title.Length - 3);
                    }

                    f.PKSchema = foreign.PKSchema;
                    f.PKTable  = foreign.PKTable;
                    f.PKColumn = foreign.PKColumn;

                    var frgfld    = schemaProvider.GetFieldInfos(connection, foreign.PKSchema, foreign.PKTable).ToList();
                    int frgPrefix = RowGenerator.DeterminePrefixLength(frgfld, z => z.FieldName);
                    var j         = new EntityJoin();
                    j.Fields = new List <EntityField>();
                    j.Name   = GenerateVariableName(f.Name.Substring(prefix));
                    if (j.Name.EndsWith("Id") || j.Name.EndsWith("ID"))
                    {
                        j.Name = j.Name.Substring(0, j.Name.Length - 2);
                    }
                    f.ForeignJoinAlias = j.Name;
                    j.SourceField      = f.Ident;

                    frgfld = frgfld.Where(y => !removeForeignFields.Contains(y.FieldName)).ToList();

                    foreach (var frg in frgfld)
                    {
                        if (frg.FieldName.Equals(foreign.PKColumn, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        var k = ToEntityField(frg, frgPrefix, config);
                        k.Flags = null;

                        //ROLEMBERG FILHO - trata o Tilte de acordo com as regras de AcertaPalavras
                        //k.Title = Inflector.Inflector.Titleize(JU(j.Name, frg.FieldName.Substring(frgPrefix)));
                        k.Title = config.ReplaceStringinDisplayName ? ToolsHeper.AcertaPalavra(Inflector.Inflector.Titleize(JU(j.Name, frg.FieldName.Substring(frgPrefix)))) :
                                  Inflector.Inflector.Titleize(JU(j.Name, frg.FieldName.Substring(frgPrefix)));
                        //ROLEMBERG FILHO - trata o Tilte de acordo com as regras de AcertaPalavras

                        k.Ident = JI(j.Name, k.Ident);
                        i       = 0;
                        ident   = k.Ident;
                        while (fieldByIdent.ContainsKey(ident))
                        {
                            ident = k.Ident + ++i;
                        }
                        k.Ident             = ident;
                        fieldByIdent[ident] = k;

                        var atk = new List <string>();
                        atk.Add("DisplayName(\"" + k.Title + "\")");
                        k.Expression = "j" + j.Name + ".[" + k.Name + "]";
                        atk.Add("Expression(\"" + k.Expression + "\")");
                        k.Attributes = String.Join(", ", atk);

                        if (f.TextualField == null && k.FieldType == "String")
                        {
                            f.TextualField = k.Ident;
                        }

                        j.Fields.Add(k);
                    }

                    model.Joins.Add(j);
                }

                model.Fields.Add(f);
            }

            if (model.NameField == null)
            {
                var fld = model.Fields.FirstOrDefault(z => z.FieldType == "String");
                if (fld != null)
                {
                    model.NameField   = fld.Ident;
                    fld.ColAttributes = fld.ColAttributes ?? "EditLink";
                }
            }

            foreach (var x in model.Fields)
            {
                var attrs = new List <string>();
                //ROLEMBERG FILHO - lookup Editor Form
                var attrsLookupEditorForm = new List <string>();
                //ROLEMBERG FILHO - lookup Editor Form

                attrs.Add("DisplayName(\"" + x.Title + "\")");

                if (x.Ident != x.Name)
                {
                    attrs.Add("Column(\"" + x.Name + "\")");
                }

                if ((x.Size ?? 0) > 0)
                {
                    attrs.Add("Size(" + x.Size + ")");
                }

                if (x.Scale > 0)
                {
                    attrs.Add("Scale(" + x.Scale + ")");
                }

                if (!String.IsNullOrEmpty(x.Flags))
                {
                    attrs.Add(x.Flags);
                }

                if (!String.IsNullOrEmpty(x.PKTable))
                {
                    attrs.Add("ForeignKey(\"" + (string.IsNullOrEmpty(x.PKSchema) ? x.PKTable : ("[" + x.PKSchema + "].[" + x.PKTable + "]")) + "\", \"" + x.PKColumn + "\")");
                    attrs.Add("LeftJoin(\"j" + x.ForeignJoinAlias + "\")");

                    //ROLEMBERG FILHO - trata o LOOKUPEDITOR
                    attrsLookupEditorForm.Add("LookupEditor(typeof(" + model.Module + ".Entities." + Serenity.CodeGenerator.RowGenerator.ClassNameFromTableName(x.PKTable) + "Row), InplaceAdd = true)");
                    //ROLEMBERG FILHO - trata o LOOKUPEDITOR
                }

                if (model.NameField == x.Ident)
                {
                    attrs.Add("QuickSearch");
                }

                if (x.TextualField != null)
                {
                    attrs.Add("TextualField(\"" + x.TextualField + "\")");
                }

                //ROLEMBERG FILHO - trata o PLACEHOLDER e ADVANCED TIPS
                //if (config.FieldDescriptionasPlaceholder)
                //{
                if (!string.IsNullOrEmpty(x.FieldDescription))
                {
                    if (x.DataType == "Boolean")
                    {
                        attrs.Add("Hint(\"" + x.FieldDescription + "\")");
                    }
                    else
                    {
                        attrs.Add("Placeholder(\"" + x.FieldDescription + "\")");
                    }
                }
                //}

                //if (config.GenerateRowswithAdvancedTips)
                //{
                string attr = processAdvancedTips(x);

                if (!string.IsNullOrEmpty(attr))
                {
                    attrs.Add(attr);
                }
                //}

                //ROLEMBERG FILHO - trata o PLACEHOLDER e ADVANCED TIPS

                x.Attributes            = String.Join(", ", attrs.ToArray());
                x.AttrsLookupEditorForm = String.Join(", ", attrsLookupEditorForm.ToArray());
                x.AttrsFileUpload       = processAdvancedTips_Image_File(x, model.Tablename);
                x.FormAttributes        = processAdvancedTips_Forms(x);
                //x.DialogAttributes = processAdvancedTips_Dialog(x, model.RootNamespace);
                processAdvancedTips_Dialog(x, ref model);
            }

            return(model);
        }
예제 #34
0
        public static EntityCodeGenerationModel GenerateModel(IDbConnection connection, string tableSchema, string table,
                                                              string module, string connectionKey, string entityClass, string permission, GeneratorConfig config)
        {
            var model = new EntityCodeGenerationModel();

            model.Module = module;

            if (connection.GetDialect() is MySqlDialect)
            {
                model.Schema = null;
            }
            else
            {
                model.Schema = tableSchema;
            }

            model.Permission    = permission;
            model.ConnectionKey = connectionKey;
            model.RootNamespace = config.RootNamespace;
            var className = entityClass ?? ClassNameFromTableName(table);

            model.ClassName    = className;
            model.RowClassName = className + "Row";
            model.Tablename    = table;
            model.Fields       = new List <EntityCodeField>();
            model.Joins        = new List <EntityCodeJoin>();
            model.Instance     = true;

            var fields   = SqlSchemaInfo.GetTableFieldInfos(connection, tableSchema, table);
            var foreigns = SqlSchemaInfo.GetTableSingleFieldForeignKeys(connection, tableSchema, table);

            var prefix = DeterminePrefixLength(fields, x => x.FieldName);

            model.FieldPrefix = fields.First().FieldName.Substring(0, prefix);

            var identity = fields.Find(f => f.IsIdentity == true);

            if (identity == null)
            {
                identity = fields.Find(f => f.IsPrimaryKey == true);
            }
            if (identity != null)
            {
                model.Identity = GenerateVariableName(identity.FieldName.Substring(prefix));
            }
            else
            {
                identity = fields.Find(f => f.IsPrimaryKey == true);
                if (identity != null)
                {
                    model.Identity = GenerateVariableName(identity.FieldName.Substring(prefix));
                }
            }

            string           baseRowMatch     = null;
            HashSet <string> baseRowFieldset  = null;
            List <string>    baseRowFieldList = new List <string>();

            foreach (var k in config.BaseRowClasses ?? new List <GeneratorConfig.BaseRowClass>())
            {
                var  b    = k.ClassName;
                var  f    = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                var  fl   = new List <string>();
                bool skip = false;
                foreach (var s in k.Fields ?? new List <string>())
                {
                    string n = s.TrimToNull();
                    if (n == null || !fields.Exists(z => z.FieldName.Substring(prefix) == n))
                    {
                        skip = true;
                        break;
                    }
                    f.Add(n);
                    fl.Add(n);
                }

                if (skip)
                {
                    continue;
                }

                if (baseRowFieldset == null || f.Count > baseRowFieldset.Count)
                {
                    baseRowFieldset  = f;
                    baseRowFieldList = fl;
                    baseRowMatch     = b;
                }
            }

            var removeForeignFields = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var s in config.RemoveForeignFields ?? new List <string>())
            {
                string n = s.TrimToNull();
                if (n != null)
                {
                    removeForeignFields.Add(n);
                }
            }

            if (baseRowFieldset != null &&
                baseRowFieldset.Count > 0)
            {
                model.RowBaseClass    = baseRowMatch;
                model.FieldsBaseClass = baseRowMatch + "Fields";
                model.RowBaseFields   = new List <EntityCodeField>();
                fields.RemoveAll(f =>
                {
                    if (baseRowFieldset.Contains(f.FieldName.Substring(prefix)))
                    {
                        var ft = SqlSchemaInfo.SqlTypeNameToFieldType(f.DataType);
                        model.RowBaseFields.Add(new EntityCodeField
                        {
                            Type        = ft,
                            TSType      = FieldTypeToTS(ft),
                            Ident       = GenerateVariableName(f.FieldName.Substring(prefix)),
                            Title       = Inflector.Inflector.Titleize(f.FieldName.Substring(prefix)),
                            Name        = f.FieldName,
                            IsValueType = ft != "String" && ft != "Stream",
                            Size        = f.Size == 0 ? (Int32?)null : f.Size,
                            Scale       = f.Scale
                        });

                        return(true);
                    }
                    return(false);
                });
            }
            else
            {
                model.RowBaseClass    = "Row";
                model.RowBaseFields   = new List <EntityCodeField>();
                model.FieldsBaseClass = "RowFieldsBase";
            }

            foreach (var field in fields)
            {
                string flags;
                if (field.IsIdentity)
                {
                    flags = "Identity";
                }
                else if (field.IsPrimaryKey)
                {
                    flags = "PrimaryKey";
                }
                else if (!field.IsNullable)
                {
                    flags = "NotNull";
                }
                else
                {
                    flags = null;
                }

                var fieldType = SqlSchemaInfo.SqlTypeNameToFieldType(field.DataType);

                var f = new EntityCodeField()
                {
                    Type        = fieldType,
                    TSType      = FieldTypeToTS(fieldType),
                    Ident       = GenerateVariableName(field.FieldName.Substring(prefix)),
                    Title       = Inflector.Inflector.Titleize(field.FieldName.Substring(prefix)),
                    Name        = field.FieldName,
                    Flags       = flags,
                    IsValueType = fieldType != "String" && fieldType != "Stream",
                    Size        = field.Size == 0 ? (Int32?)null : field.Size,
                    Scale       = field.Scale
                };

                if (f.Name == className && fieldType == "String")
                {
                    model.NameField = f.Name;
                }

                var foreign = foreigns.Find((k) => k.FKColumn.Equals(field.FieldName, StringComparison.InvariantCultureIgnoreCase));
                if (foreign != null)
                {
                    if (f.Title.EndsWith(" Id") && f.Title.Length > 3)
                    {
                        f.Title = f.Title.SafeSubstring(0, f.Title.Length - 3);
                    }

                    f.PKSchema = foreign.PKSchema;
                    f.PKTable  = foreign.PKTable;
                    f.PKColumn = foreign.PKColumn;

                    var frgfld    = SqlSchemaInfo.GetTableFieldInfos(connection, foreign.PKSchema, foreign.PKTable);
                    int frgPrefix = RowGenerator.DeterminePrefixLength(frgfld, z => z.FieldName);
                    var j         = new EntityCodeJoin();
                    j.Fields = new List <EntityCodeField>();
                    j.Name   = GenerateVariableName(f.Name.Substring(prefix));
                    if (j.Name.EndsWith("Id") || j.Name.EndsWith("ID"))
                    {
                        j.Name = j.Name.Substring(0, j.Name.Length - 2);
                    }
                    f.ForeignJoinAlias = j.Name;
                    j.SourceField      = f.Ident;

                    frgfld.RemoveAll(y => removeForeignFields.Contains(y.FieldName));

                    if (frgfld.Find(y => y.FieldName.Substring(frgPrefix) == "SonGuncelleyenID") != null)
                    {
                        //frgfld.RemoveAll(y => LoggingBaseFields.Contains(y.FieldName.Substring(frgPrefix)));
                    }

                    foreach (var frg in frgfld)
                    {
                        if (frg.FieldName.Equals(foreign.PKColumn, StringComparison.InvariantCultureIgnoreCase))
                        {
                            continue;
                        }

                        var kType = SqlSchemaInfo.SqlTypeNameToFieldType(frg.DataType);

                        var k = new EntityCodeField()
                        {
                            Type        = kType,
                            TSType      = FieldTypeToTS(kType),
                            Ident       = GenerateVariableName(frg.FieldName.Substring(frgPrefix)),
                            Title       = Inflector.Inflector.Titleize(JU(j.Name, frg.FieldName.Substring(frgPrefix))),
                            Name        = frg.FieldName,
                            Flags       = flags,
                            IsValueType = kType != "String" && kType != "Stream",
                            Size        = frg.Size == 0 ? (Int32?)null : frg.Size,
                            Scale       = frg.Scale
                        };

                        if (f.TextualField == null && kType == "String")
                        {
                            f.TextualField = JI(j.Name, k.Ident);
                        }

                        j.Fields.Add(k);
                    }

                    model.Joins.Add(j);
                }

                model.Fields.Add(f);
            }

            if (model.NameField == null)
            {
                var fld = model.Fields.FirstOrDefault(z => z.Type == "String");
                if (fld != null)
                {
                    model.NameField = fld.Ident;
                }
            }

            return(model);
        }
예제 #35
0
        public void Run(string projectJson, string[] args)
        {
            var projectDir = Path.GetDirectoryName(projectJson);

            var outFile       = args.FirstOrDefault(x => x.StartsWith("-o:"))?.Substring(3).TrimToNull();
            var connectionKey = args.FirstOrDefault(x => x.StartsWith("-c:"))?.Substring(3).TrimToNull();
            var table         = args.FirstOrDefault(x => x.StartsWith("-t:"))?.Substring(3).TrimToNull();
            var what          = args.FirstOrDefault(x => x.StartsWith("-w:"))?.Substring(3).TrimToNull();
            var module        = args.FirstOrDefault(x => x.StartsWith("-m:"))?.Substring(3).TrimToNull();
            var identifier    = args.FirstOrDefault(x => x.StartsWith("-i:"))?.Substring(3).TrimToNull();
            var permissionKey = args.FirstOrDefault(x => x.StartsWith("-p:"))?.Substring(3).TrimToNull();

            if (identifier != null)
            {
                CodeFileHelper.Overwrite = true;
            }

            var config         = GeneratorConfig.LoadFromFile(Path.Combine(projectDir, "sergen.json"));
            var connectionKeys = config.Connections
                                 .Where(x => !x.ConnectionString.IsEmptyOrNull())
                                 .Select(x => x.Key).ToList();

            var appSettingsFile = Path.Combine(projectDir, "appsettings.json");
            AppSettingsFormat appSettings;

            if (File.Exists(appSettingsFile))
            {
                appSettings = JSON.ParseTolerant <AppSettingsFormat>(File.ReadAllText(appSettingsFile).TrimToNull() ?? "{}");
            }
            else
            {
                appSettings = new AppSettingsFormat();
            }

            connectionKeys.AddRange(appSettings.Data.Keys);

            var appSettingsFile2 = Path.Combine(projectDir, "appsettings.machine.json");

            if (File.Exists(appSettingsFile2))
            {
                var appSettings2 = JSON.ParseTolerant <AppSettingsFormat>(File.ReadAllText(appSettingsFile2).TrimToNull() ?? "{}");
                foreach (var pair in appSettings2.Data)
                {
                    appSettings.Data[pair.Key] = pair.Value;
                }
            }

            connectionKeys.AddRange(appSettings.Data.Keys);

            connectionKeys = connectionKeys.Distinct(StringComparer.OrdinalIgnoreCase).OrderBy(x => x).ToList();

            if (connectionKeys.Count == 0)
            {
                Console.Error.WriteLine("No connections in appsettings.json or sergen.json!");
                Environment.Exit(1);
            }

            if (outFile == null && connectionKey == null)
            {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("=== Table Code Generation ===");
                Console.WriteLine("");
                Console.ResetColor();

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Available Connections:");
                Console.ResetColor();
                foreach (var x in connectionKeys)
                {
                    Console.WriteLine(x);
                }
                Console.ResetColor();
                Console.WriteLine();
            }
            else if (connectionKey == null)
            {
                File.WriteAllText(outFile, JSON.Stringify(connectionKeys));
                Environment.Exit(0);
            }

            string userInput = null;

            if (outFile == null && connectionKey == null)
            {
                userInput = connectionKeys.Count == 1 ? connectionKeys[0] : null;
                while (connectionKey == null ||
                       !connectionKeys.Contains(connectionKey, StringComparer.OrdinalIgnoreCase))
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Enter a Connection: ('!' to abort)");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    connectionKey           = Hinter.ReadHintedLine(connectionKeys, userInput: userInput);
                    userInput = connectionKey;

                    if (connectionKey == "!")
                    {
                        Console.ResetColor();
                        return;
                    }
                }
            }

            userInput     = connectionKey;
            connectionKey = connectionKeys.Find(x => string.Compare(x, userInput, StringComparison.OrdinalIgnoreCase) == 0);
            if (connectionKey == null)
            {
                Console.Error.WriteLine("Can't find connection with key: " + userInput + "!");
                Environment.Exit(1);
            }

            if (outFile == null)
            {
                Console.ResetColor();
                Console.WriteLine();
            }

            var dataConnection = appSettings.Data.ContainsKey(connectionKey) ?
                                 appSettings.Data[connectionKey] : null;

            var confConnection = config.Connections.FirstOrDefault(x =>
                                                                   string.Compare(x.Key, connectionKey, StringComparison.OrdinalIgnoreCase) == 0);

            var connectionString = dataConnection != null?dataConnection.ConnectionString.TrimToNull() : null;

            if (connectionString == null && confConnection != null)
            {
                connectionString = confConnection.ConnectionString.TrimToNull();
            }

            var providerName = dataConnection != null?dataConnection.ProviderName.TrimToNull() : null;

            if (providerName == null && confConnection != null)
            {
                providerName = confConnection.ProviderName.TrimToNull();
            }
            providerName = providerName ?? "System.Data.SqlClient";

            DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance);
            DbProviderFactories.RegisterFactory("Microsoft.Data.Sqlite", Microsoft.Data.Sqlite.SqliteFactory.Instance);
            DbProviderFactories.RegisterFactory("Npgsql", Npgsql.NpgsqlFactory.Instance);
            DbProviderFactories.RegisterFactory("FirebirdSql.Data.FirebirdClient", FirebirdSql.Data.FirebirdClient.FirebirdClientFactory.Instance);
            DbProviderFactories.RegisterFactory("MySql.Data.MySqlClient", MySql.Data.MySqlClient.MySqlClientFactory.Instance);

            if (connectionString.IndexOf("../../..") >= 0)
            {
                connectionString = connectionString.Replace("../../..", Path.GetDirectoryName(projectJson));
            }
            else if (connectionString.IndexOf(@"..\..\..\") >= 0)
            {
                connectionString = connectionString.Replace(@"..\..\..\", Path.GetDirectoryName(projectJson));
            }

            ISchemaProvider  schemaProvider;
            List <TableName> tableNames;

            using (var connection = SqlConnections.New(connectionString, providerName))
            {
                schemaProvider = SchemaHelper.GetSchemaProvider(connection.GetDialect().ServerType);
                tableNames     = schemaProvider.GetTableNames(connection).ToList();
            }

            var tables = tableNames.Select(x => x.Tablename).ToList();

            if (outFile == null && table == null)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Available Tables:");
                Console.ResetColor();

                foreach (var x in tables)
                {
                    Console.WriteLine(x);
                }
            }
            else if (table == null)
            {
                File.WriteAllText(outFile, JSON.Stringify(tableNames.Select(x =>
                {
                    var xct = confConnection == null ? null : confConnection.Tables.FirstOrDefault(z => string.Compare(z.Tablename, table, StringComparison.OrdinalIgnoreCase) == 0);
                    return(new
                    {
                        name = x.Tablename,
                        module = xct == null || xct.Module.IsEmptyOrNull() ? RowGenerator.ClassNameFromTableName(connectionKey) : xct.Module,
                        permission = xct == null || xct.PermissionKey.IsTrimmedEmpty() ? "Administration:General" : xct.PermissionKey,
                        identifier = xct == null || xct.Identifier.IsEmptyOrNull() ? RowGenerator.ClassNameFromTableName(x.Table) : xct.Identifier,
                    });
                })));

                Environment.Exit(0);
            }

            userInput = tables.Count == 1 ? tables[0] : null;
            if (userInput == null && schemaProvider.DefaultSchema != null &&
                tables.Any(x => x.StartsWith(schemaProvider.DefaultSchema + ".")))
            {
                userInput = schemaProvider.DefaultSchema + ".";
            }

            if (outFile == null)
            {
                Console.WriteLine();

                while (table == null ||
                       !tables.Contains(table, StringComparer.OrdinalIgnoreCase))
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Enter a Table: ('!' to abort)");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    table     = Hinter.ReadHintedLine(tables, userInput: userInput);
                    userInput = table;

                    if (table == "!")
                    {
                        Console.ResetColor();
                        return;
                    }
                }
            }

            userInput = table;
            var tableName = tableNames.First(x => string.Compare(x.Tablename, userInput, StringComparison.OrdinalIgnoreCase) == 0);

            if (tableName == null)
            {
                Console.Error.WriteLine("Can't find table with name: " + userInput + "!");
                Environment.Exit(1);
            }

            var confTable = confConnection == null ? null : confConnection.Tables.FirstOrDefault(x =>
                                                                                                 string.Compare(x.Tablename, table, StringComparison.OrdinalIgnoreCase) == 0);

            if (module == null)
            {
                userInput = confTable == null || confTable.Module.IsEmptyOrNull() ?
                            RowGenerator.ClassNameFromTableName(connectionKey) : confTable.Module;

                Console.WriteLine();

                while (module.IsTrimmedEmpty())
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Enter a Module name for table: ('!' to abort)");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    module    = Hinter.ReadHintedLine(new string[0], userInput: userInput);
                    userInput = module;

                    if (module == "!")
                    {
                        Console.ResetColor();
                        return;
                    }
                }
            }

            if (identifier == null)
            {
                userInput = confTable == null || confTable.Identifier.IsEmptyOrNull() ?
                            RowGenerator.ClassNameFromTableName(tableName.Table) : confTable.Identifier;

                Console.WriteLine();

                while (identifier.IsTrimmedEmpty())
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Enter a class Identifier for table: ('!' to abort)");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    identifier = Hinter.ReadHintedLine(new string[0], userInput: userInput);
                    userInput  = identifier;

                    if (identifier == "!")
                    {
                        Console.ResetColor();
                        return;
                    }
                }
            }

            if (permissionKey == null)
            {
                userInput = confTable == null || confTable.PermissionKey.IsTrimmedEmpty() ?
                            "Administration:General" : confTable.PermissionKey;

                Console.WriteLine();

                while (permissionKey.IsTrimmedEmpty())
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Enter a Permission Key for table: ('!' to abort)");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    permissionKey           = Hinter.ReadHintedLine(new string[0], userInput: userInput);
                    userInput = permissionKey;

                    if (permissionKey == "!")
                    {
                        Console.ResetColor();
                        return;
                    }
                }
            }


            if (what == null)
            {
                Console.WriteLine();

                userInput = "RSU";
                while (what.IsEmptyOrNull())
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Choose What to Generate (R:Row, S:Repo+Svc, U=Cols+Form+Page+Grid+Dlg+Css)");
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    what      = Hinter.ReadHintedLine(new string[0], userInput: userInput);
                    userInput = what;

                    if (what == "!")
                    {
                        Console.ResetColor();
                        return;
                    }
                }
            }

            config.GenerateRow     = what.IndexOf("R", StringComparison.OrdinalIgnoreCase) >= 0;
            config.GenerateService = what.IndexOf("S", StringComparison.OrdinalIgnoreCase) >= 0;
            config.GenerateUI      = what.IndexOf("U", StringComparison.OrdinalIgnoreCase) >= 0;

            Console.ResetColor();
            Console.WriteLine();

            if (confConnection == null)
            {
                confConnection = new GeneratorConfig.Connection
                {
                    Key = connectionKey
                };
                config.Connections.Add(confConnection);
            }

            if (confTable == null)
            {
                confTable = new GeneratorConfig.Table
                {
                    Identifier    = identifier,
                    Module        = module,
                    PermissionKey = permissionKey,
                    Tablename     = tableName.Tablename
                };

                confConnection.Tables.Add(confTable);
            }
            else
            {
                confTable.Identifier    = identifier;
                confTable.Module        = module;
                confTable.PermissionKey = permissionKey;
            }

            File.WriteAllText(Path.Combine(projectDir, "sergen.json"), config.SaveToJson());

            using (var connection = SqlConnections.New(connectionString, providerName))
            {
                connection.Open();

                var rowModel = RowGenerator.GenerateModel(connection, tableName.Schema, tableName.Table,
                                                          module, connectionKey, identifier, permissionKey, config);

                new EntityCodeGenerator(rowModel, config, projectJson).Run();
            }
        }
예제 #36
0
        public ExitCodes Run(string csproj)
        {
            if (csproj == null)
            {
                throw new ArgumentNullException(nameof(csproj));
            }

            if (!File.Exists(csproj))
            {
                Console.Error.WriteLine($"Project file {csproj} is not found!");
                return(ExitCodes.ProjectNotFound);
            }

            var visited = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            Func <string, bool> skipPackage = id =>
            {
                if (visited.Contains(id))
                {
                    return(true);
                }

                if (CodeGeneration.SkipPackages.ForRestore(id))
                {
                    return(true);
                }

                visited.Add(id);

                return(false);
            };

            var projectDir = Path.GetDirectoryName(csproj);
            var config     = GeneratorConfig.LoadFromFile(Path.Combine(projectDir, "sergen.json"));

            GlobFilter include = null;

            if (config.Restore?.Include.IsEmptyOrNull() == false)
            {
                include = new GlobFilter(config.Restore.Include);
            }

            GlobFilter exclude = null;

            if (config.Restore?.Exclude.IsEmptyOrNull() == false)
            {
                exclude = new GlobFilter(config.Restore.Exclude);
            }

            var targetRoot = Path.GetDirectoryName(csproj);
            var restoredFromProjectReference = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            void restoreFile(string file, string relative)
            {
                relative = PathHelper.ToPath(relative);

                if (include != null &&
                    !include.IsMatch(relative))
                {
                    return;
                }

                if (exclude != null &&
                    exclude.IsMatch(relative))
                {
                    return;
                }

                if (restoredFromProjectReference.Contains(relative))
                {
                    return;
                }

                var target = Path.Combine(targetRoot, relative);

                if (File.Exists(target))
                {
                    if (!File.ReadAllBytes(target)
                        .SequenceEqual(File.ReadAllBytes(file)))
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine("Restoring: " + relative);
                        Console.ResetColor();
                        File.Copy(file, target, true);
                    }
                }
                else
                {
                    if (!Directory.Exists(target))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(target));
                    }

                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Restoring: " + relative);
                    Console.ResetColor();
                    File.Copy(file, target, false);
                }
            }

            try
            {
                foreach (var reference in EnumerateProjectReferences(csproj, new HashSet <string>(StringComparer.OrdinalIgnoreCase)))
                {
                    IBuildProject project;
                    try
                    {
                        project = ProjectSystem.LoadProject(reference);
                    }
                    catch
                    {
                        continue;
                    }

                    foreach (var item in project.AllEvaluatedItems
                             .Where(x =>
                                    string.Equals(x.ItemType, "TypingsToPackage", StringComparison.OrdinalIgnoreCase) ||
                                    string.Equals(x.ItemType, "Content", StringComparison.OrdinalIgnoreCase) ||
                                    string.Equals(x.ItemType, "None", StringComparison.OrdinalIgnoreCase) ||
                                    string.Equals(x.ItemType, "TypeScriptCompile", StringComparison.OrdinalIgnoreCase))
                             .Where(x => x.EvaluatedInclude?.EndsWith(".d.ts",
                                                                      StringComparison.OrdinalIgnoreCase) == true))
                    {
                        var sourceFile = Path.Combine(Path.GetDirectoryName(reference),
                                                      item.EvaluatedInclude);

                        if (!File.Exists(sourceFile))
                        {
                            continue;
                        }

                        if (!string.Equals(item.ItemType, "TypingsToPackage", StringComparison.OrdinalIgnoreCase) &&
                            item.GetMetadataValue("Pack") != "true")
                        {
                            continue;
                        }

                        var packagePath = item.GetMetadataValue("PackagePath")?.Trim();
                        if (!string.IsNullOrEmpty(packagePath))
                        {
                            foreach (var path in packagePath.Split(';', StringSplitOptions.RemoveEmptyEntries))
                            {
                                if (!PathHelper.ToUrl(path).StartsWith("typings/", StringComparison.OrdinalIgnoreCase))
                                {
                                    continue;
                                }

                                restoreFile(sourceFile, path);
                                restoredFromProjectReference.Add(path);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
            }

            var packagesDir = PackageHelper.DeterminePackagesPath(FileSystem);

            if (packagesDir == null)
            {
                Console.Error.WriteLine("Can't determine NuGet packages directory!");
                return(ExitCodes.CantDeterminePackagesDir);
            }

            var queue = new Queue <(string ID, string Version)>();

            foreach (var x in EnumeratePackageReferences(csproj))
            {
                if (!skipPackage(x.Id) && !string.IsNullOrEmpty(x.Version))
                {
                    queue.Enqueue(x);
                }
            }
            ;

            while (queue.Count > 0)
            {
                var dep = queue.Dequeue();
                var id  = dep.ID;

                var ver = dep.Version.Trim();
                if (ver.EndsWith("-*", StringComparison.Ordinal))
                {
                    ver = ver.Substring(0, ver.Length - 2);
                }
                else if (ver.StartsWith("[", StringComparison.Ordinal) && ver.EndsWith("]", StringComparison.Ordinal))
                {
                    ver = ver[1..^ 1].Trim();
예제 #37
0
        public static EntityModel GenerateModel(IDbConnection connection, string tableSchema, string table,
                                                string module, string connectionKey, string entityClass, string permission, GeneratorConfig config)
        {
            var model = new EntityModel();

            model.Module = module;

            if (connection.GetDialect().ServerType.StartsWith("MySql", StringComparison.OrdinalIgnoreCase))
            {
                model.Schema = null;
            }
            else
            {
                model.Schema = tableSchema;
            }

            model.Permission    = permission;
            model.ConnectionKey = connectionKey;
            model.RootNamespace = config.RootNamespace;
            var className = entityClass ?? ClassNameFromTableName(table);

            model.ClassName    = className;
            model.RowClassName = className + "Row";
            model.Title        = Inflector.Inflector.Titleize(className);
            model.Tablename    = table;
            model.Fields       = new List <EntityField>();
            model.Joins        = new List <EntityJoin>();
            model.Instance     = true;

            var schemaProvider = SchemaHelper.GetSchemaProvider(connection.GetDialect().ServerType);
            var fields         = schemaProvider.GetFieldInfos(connection, tableSchema, table).ToList();

            if (!fields.Any(x => x.IsPrimaryKey))
            {
                var primaryKeys = new HashSet <string>(schemaProvider.GetPrimaryKeyFields(connection, tableSchema, table));
                foreach (var field in fields)
                {
                    field.IsPrimaryKey = primaryKeys.Contains(field.FieldName);
                }
            }

            if (!fields.Any(x => x.IsIdentity))
            {
                var identities = new HashSet <string>(schemaProvider.GetIdentityFields(connection, tableSchema, table));
                foreach (var field in fields)
                {
                    field.IsIdentity = identities.Contains(field.FieldName);
                }
            }

            var foreigns = schemaProvider.GetForeignKeys(connection, tableSchema, table)
                           .ToLookup(x => x.FKName)
                           .Where(x => x.Count() == 1)
                           .SelectMany(x => x)
                           .ToList();

            foreach (var field in fields)
            {
                var fk = foreigns.FirstOrDefault(x => x.FKColumn == field.FieldName);
                if (fk != null)
                {
                    field.PKSchema = fk.PKSchema;
                    field.PKTable  = fk.PKTable;
                    field.PKColumn = fk.PKColumn;
                }
            }

            var prefix = DeterminePrefixLength(fields, x => x.FieldName);

            model.FieldPrefix = fields.First().FieldName.Substring(0, prefix);

            var identity = fields.FirstOrDefault(f => f.IsIdentity == true);

            if (identity == null)
            {
                identity = fields.FirstOrDefault(f => f.IsPrimaryKey == true);
            }
            if (identity != null)
            {
                model.Identity = GenerateVariableName(identity.FieldName.Substring(prefix));
            }
            else
            {
                identity = fields.FirstOrDefault(f => f.IsPrimaryKey == true) ??
                           fields.FirstOrDefault();
                if (identity != null)
                {
                    model.Identity = GenerateVariableName(identity.FieldName.Substring(prefix));
                }
            }

            string           baseRowMatch     = null;
            HashSet <string> baseRowFieldset  = null;
            List <string>    baseRowFieldList = new List <string>();

            foreach (var k in config.BaseRowClasses ?? new List <GeneratorConfig.BaseRowClass>())
            {
                var  b    = k.ClassName;
                var  f    = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                var  fl   = new List <string>();
                bool skip = false;
                foreach (var s in k.Fields ?? new List <string>())
                {
                    string n = s.TrimToNull();
                    if (n == null || !fields.Any(z => z.FieldName.Substring(prefix) == n))
                    {
                        skip = true;
                        break;
                    }
                    f.Add(n);
                    fl.Add(n);
                }

                if (skip)
                {
                    continue;
                }

                if (baseRowFieldset == null || f.Count > baseRowFieldset.Count)
                {
                    baseRowFieldset  = f;
                    baseRowFieldList = fl;
                    baseRowMatch     = b;
                }
            }

            var removeForeignFields = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var s in config.RemoveForeignFields ?? new List <string>())
            {
                string n = s.TrimToNull();
                if (n != null)
                {
                    removeForeignFields.Add(n);
                }
            }

            if (baseRowFieldset != null &&
                baseRowFieldset.Count > 0)
            {
                model.RowBaseClass    = baseRowMatch;
                model.FieldsBaseClass = baseRowMatch + "Fields";
                model.RowBaseFields   = new List <EntityField>();
                fields = fields.Where(f =>
                {
                    if (baseRowFieldset.Contains(f.FieldName.Substring(prefix)))
                    {
                        var ef   = ToEntityField(f, prefix);
                        ef.Flags = null;
                        model.RowBaseFields.Add(ef);
                        return(false);
                    }
                    return(true);
                }).ToList();
            }
            else
            {
                model.RowBaseClass    = "Row";
                model.RowBaseFields   = new List <EntityField>();
                model.FieldsBaseClass = "RowFieldsBase";
            }

            var fieldByIdent = new Dictionary <string, EntityField>(StringComparer.OrdinalIgnoreCase);

            foreach (var field in fields)
            {
                var f = ToEntityField(field, prefix);

                if (f.Ident == model.IdField)
                {
                    f.ColAttributes = "EditLink, DisplayName(\"Db.Shared.RecordId\"), AlignRight";
                }

                int    i     = 0;
                string ident = f.Ident;
                while (fieldByIdent.ContainsKey(ident))
                {
                    ident = f.Ident + ++i;
                }
                f.Ident             = ident;
                fieldByIdent[ident] = f;

                if (f.Name == className && f.FieldType == "String")
                {
                    model.NameField = f.Name;
                    f.ColAttributes = f.ColAttributes ?? "EditLink";
                }

                var foreign = foreigns.Find((k) => k.FKColumn.Equals(field.FieldName, StringComparison.OrdinalIgnoreCase));
                if (foreign != null)
                {
                    if (f.Title.EndsWith(" Id") && f.Title.Length > 3)
                    {
                        f.Title = f.Title.SafeSubstring(0, f.Title.Length - 3);
                    }

                    f.PKSchema = foreign.PKSchema;
                    f.PKTable  = foreign.PKTable;
                    f.PKColumn = foreign.PKColumn;

                    var frgfld    = schemaProvider.GetFieldInfos(connection, foreign.PKSchema, foreign.PKTable).ToList();
                    int frgPrefix = RowGenerator.DeterminePrefixLength(frgfld, z => z.FieldName);
                    var j         = new EntityJoin();
                    j.Fields = new List <EntityField>();
                    j.Name   = GenerateVariableName(f.Name.Substring(prefix));
                    if (j.Name.EndsWith("Id") || j.Name.EndsWith("ID"))
                    {
                        j.Name = j.Name.Substring(0, j.Name.Length - 2);
                    }
                    f.ForeignJoinAlias = j.Name;
                    j.SourceField      = f.Ident;

                    frgfld = frgfld.Where(y => !removeForeignFields.Contains(y.FieldName)).ToList();

                    foreach (var frg in frgfld)
                    {
                        if (frg.FieldName.Equals(foreign.PKColumn, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        var k = ToEntityField(frg, frgPrefix);
                        k.Flags = null;
                        k.Title = Inflector.Inflector.Titleize(JU(j.Name, frg.FieldName.Substring(frgPrefix)));
                        k.Ident = JI(j.Name, k.Ident);
                        i       = 0;
                        ident   = k.Ident;
                        while (fieldByIdent.ContainsKey(ident))
                        {
                            ident = k.Ident + ++i;
                        }
                        k.Ident             = ident;
                        fieldByIdent[ident] = k;

                        var atk = new List <string>();
                        atk.Add("DisplayName(\"" + k.Title + "\")");
                        k.Expression = "j" + j.Name + ".[" + k.Name + "]";
                        atk.Add("Expression(\"" + k.Expression + "\")");
                        k.Attributes = String.Join(", ", atk);

                        if (f.TextualField == null && k.FieldType == "String")
                        {
                            f.TextualField = k.Ident;
                        }

                        j.Fields.Add(k);
                    }

                    model.Joins.Add(j);
                }

                model.Fields.Add(f);
            }

            if (model.NameField == null)
            {
                var fld = model.Fields.FirstOrDefault(z => z.FieldType == "String");
                if (fld != null)
                {
                    model.NameField   = fld.Ident;
                    fld.ColAttributes = fld.ColAttributes ?? "EditLink";
                }
            }

            foreach (var x in model.Fields)
            {
                var attrs = new List <string>();
                attrs.Add("DisplayName(\"" + x.Title + "\")");

                if (x.Ident != x.Name)
                {
                    attrs.Add("Column(\"" + x.Name + "\")");
                }

                if ((x.Size ?? 0) > 0)
                {
                    attrs.Add("Size(" + x.Size + ")");
                }

                if (x.Scale > 0)
                {
                    attrs.Add("Scale(" + x.Scale + ")");
                }

                if (!String.IsNullOrEmpty(x.Flags))
                {
                    attrs.Add(x.Flags);
                }

                if (!String.IsNullOrEmpty(x.PKTable))
                {
                    attrs.Add("ForeignKey(\"" + (string.IsNullOrEmpty(x.PKSchema) ? x.PKTable : ("[" + x.PKSchema + "].[" + x.PKTable + "]")) + "\", \"" + x.PKColumn + "\")");
                    attrs.Add("LeftJoin(\"j" + x.ForeignJoinAlias + "\")");
                }

                if (model.NameField == x.Ident)
                {
                    attrs.Add("QuickSearch");
                }

                if (x.TextualField != null)
                {
                    attrs.Add("TextualField(\"" + x.TextualField + "\")");
                }

                x.Attributes = String.Join(", ", attrs.ToArray());
            }

            return(model);
        }