Dynamic SQL Editor is a Windows Forms application designed to provide a flexible and configurable interface for browsing and editing data in Microsoft SQL Server databases. Instead of requiring developers to build custom UI screens for every table, this tool dynamically generates data views, detail forms, filters, and related data tabs based on database schema and a custom configuration Domain-Specific Language (DSL).
This allows users (like administrators, support staff, or developers) to quickly view, filter, sort, page through, and perform CRUD (Create, Read, Update, Delete) operations on tables without needing dedicated application features for each one.
- Dynamic UI Generation: Creates data grids, detail editing forms, and related data views based on database schema and configuration.
- Configuration Driven: Uses simple
.dsltext files to control behavior, appearance, and available features per table. - Schema Discovery: Automatically detects tables, views, columns, primary keys, and foreign keys.
- CRUD Operations: Supports viewing, creating, updating, and deleting records with basic concurrency handling (using
timestamp/rowversioncolumns if available). - Data Grid:
- Displays table data in a familiar grid format.
- Column visibility and headers configurable.
- Basic data formatting for dates and numbers.
- Paging: Efficiently handles large tables using server-side paging (supports
OFFSET/FETCHand fallbackROW_NUMBER()). Configurable page size. - Sorting: Allows sorting data by clicking column headers. Default sort order configurable.
- Filtering:
- Define pre-set filters with custom
WHEREclauses in the configuration. - Supports filters that require user input (text or lookup values).
- Configurable default filter per table.
- Define pre-set filters with custom
- Detail View/Editor:
- Dynamically generated form for viewing/editing individual records.
- Control types inferred from data types (TextBox, CheckBox, DateTimePicker) or explicitly configured (MultiLine TextBox, ComboBox, Label, etc.).
- Nullable field support with dedicated "Is Null" checkboxes.
- Configurable field visibility, read-only status, labels, and display order.
- Foreign Key Support:
- Automatically detects foreign keys.
- Displays FK columns as ComboBoxes in the detail view.
- Populates ComboBoxes using configurable lookups (
FKLookup.*) or heuristics based on column names (Name,Description,*ID, etc. - configurable globally).
- Related Data Tabs:
- Automatically discovers and displays related child data (based on foreign keys referencing the current table).
- Configurable explicit child relationships (
RelatedChild.*). - Lazy loading of related data when a tab is selected.
- Custom Actions:
- Define custom buttons (
ActionButton.*) that execute external commands or scripts. - Can pass data from the selected row as command-line arguments.
- Execution can be globally disabled for security.
- Define custom buttons (
- Configuration Merging: Supports a base
AppConfig.dsland database-specific overrides (<DatabaseName>.dsl). - Logging: Logs operations and errors to files in a
Logsdirectory. - Error Handling: Global exception handlers capture and log unhandled errors.
- .NET Framework: Version 4.8 (as specified in
DynamicSqlEditor.csproj). - SQL Server: Access to a Microsoft SQL Server database (tested primarily with SQL Server, compatibility with Azure SQL Database is likely but may need verification, especially regarding schema queries).
- Visual Studio: Required for building the project (e.g., Visual Studio 2019 or later with .NET desktop development workload).
- Clone or Download: Get the source code from the repository.
- Open in Visual Studio: Open the
DynamicSqlEditor.slnsolution file (if available) or theDynamicSqlEditor.csprojproject file. - Restore NuGet Packages: Visual Studio should automatically restore any necessary packages upon opening (though this project seems to use only framework assemblies).
- Configure Connection:
- Locate the
Configdirectory in the project's root. If it doesn't exist, create it. - Create or edit the
AppConfig.dslfile within theConfigdirectory. - Add a
[Connection]section and set theConnectionStringkey. See the Configuration section below for details. - Example
Config/AppConfig.dsl:[Connection] ConnectionString = Server=your_server_name;Database=your_database_name;Integrated Security=True; # Or User ID=...;Password=...; QueryTimeout = 60 # Optional: Default query timeout in seconds
- Locate the
- Build: Build the solution (Build > Build Solution or Ctrl+Shift+B).
- Run:
- Run the project from Visual Studio (press F5).
- Alternatively, navigate to the output directory (e.g.,
bin\Debugorbin\Release) and runDynamicSqlEditor.exe.
The application's behavior is heavily controlled by configuration files located in the Config directory.
- Sections: Defined by square brackets, e.g.,
[Connection]. Section names are case-insensitive. - Key-Value Pairs: Settings within sections are defined as
Key = Value. Keys are case-insensitive. - Comments: Lines starting with
#are ignored. - Attributes: Some values contain comma-separated attributes, often in the format
AttributeName="Value"orAttributeName=Value. Values with spaces should be quoted. Parsing is case-insensitive for attribute names.
- Base Configuration: The application first loads
Config\AppConfig.dsl. This file should contain common settings or defaults. - Database-Specific Configuration: After successfully connecting to a database, the application attempts to load
Config\<DatabaseName>.dsl(e.g.,Config\MyDatabase.dsl). Settings in this file overwrite any settings with the same section and key loaded fromAppConfig.dsl. This allows for database-specific customizations.
Defines how to connect to the SQL Server database.
ConnectionString(Required): The standard ADO.NET connection string.QueryTimeout(Optional): Default command timeout in seconds for SQL queries. Defaults to60.
Defines application-wide settings and schema filtering rules.
IncludeSchemas(Optional): Comma-separated list of schemas to include. Supports wildcards (*,?,%). If omitted, all schemas are considered initially. Example:dbo, sales, hr*ExcludeTables(Optional): Comma-separated list of tables (inSchema.Tableformat) to exclude. Supports wildcards. Applied afterIncludeSchemas. Example:dbo.sysdiagrams, dbo.%audit%DefaultFKDisplayHeuristic(Optional): Comma-separated, ordered list of column names or patterns used to automatically find the best display column for foreign key ComboBoxes when not explicitly configured viaFKLookup. Defaults toName, Description, Title, *ID.DisableCustomActionExecution(Optional):TrueorFalse. IfTrue, preventsActionButtoncommands from being executed. Useful for security. Defaults toFalse.
Defines settings specific to a particular table or view. Replace SchemaName.TableName with the actual schema and table name (e.g., [Table:dbo.Customers]).
CustomSelectQuery(Optional): Allows providing a completely custom SQL query for fetching data for the grid and detail view.- Crucial: Must contain the placeholders
{WHERE},{ORDERBY}, and{PAGING}which the application will replace. - Example:
SELECT c.CustomerID, c.Name, a.City FROM Customers c JOIN Addresses a ON c.AddressID = a.AddressID {WHERE} {ORDERBY} {PAGING} - Warning: Use with caution. Ensure the query is secure and performs well. The application does not heavily sanitize this query.
- Crucial: Must contain the placeholders
DefaultSortColumn(Optional): The column name to sort by default when the view loads.DefaultSortDirection(Optional):AscendingorDescending. Defaults toAscending.Filter.Default(Optional): Specifies the default filter to apply when the view loads. Only applies if the filter does not require input.- Attributes:
FilterName(Required): The name of the filter defined below (e.g.,FilterName=ActiveCustomers).
- Attributes:
Filter.<FilterName>(Optional, Multiple): Defines a named filter available in the filter dropdown. Replace<FilterName>with a unique name (e.g.,Filter.ActiveCustomers).- Attributes:
Label(Required): The text displayed in the dropdown list (e.g.,Label="Active Customers").WhereClause(Required): The SQLWHEREclause condition (without theWHEREkeyword). Parameters can be used ifRequiresInputis set (e.g.,WhereClause="IsActive = 1 AND Country = @Country").RequiresInput(Optional): Comma-separated list of parameter names the user must provide. If a parameter needs a lookup, useParamName:LookupType.LookupTypecan be a table name (Schema.Table) or potentially a namedFKLookupdefinition (needs verification). Example:RequiresInput="StartDate, EndDate, Country:dbo.Countries".
- Attributes:
DetailFormField.<ColumnName>(Optional, Multiple): Customizes the appearance and behavior of a specific column in the detail editing panel. Replace<ColumnName>with the actual column name.- Attributes:
Label(Optional): Overrides the default label text (which is the column name).Order(Optional): An integer determining the display order in the detail form (lower numbers appear first). Defaults to a high value (schema order).ReadOnly(Optional):TrueorFalse. Forces the field to be read-only, overriding default behavior (PKs, Identity, Computed, Timestamp are read-only by default).Visible(Optional):TrueorFalse. Hides or shows the field in the detail form. Defaults based on data type (complex types like XML, spatial are hidden by default).ControlType(Optional): Explicitly sets the control type. Useful for overriding defaults. Values:TextBox,TextBoxMultiLine,ComboBox,CheckBox,DateTimePicker,Label.Defaultuses automatic detection.
- Attributes:
FKLookup.<FKColumnName>(Optional, Multiple): Explicitly configures the lookup behavior for a foreign key column's ComboBox in the detail view. Replace<FKColumnName>with the foreign key column name in this table. Overrides automatic FK detection and heuristics for this column.- Attributes:
ReferencedTable(Required): The table being looked up (formatSchema.TableName, e.g.,ReferencedTable=dbo.Countries).DisplayColumn(Required): The column fromReferencedTableto display in the ComboBox dropdown (e.g.,DisplayColumn=CountryName).ValueColumn(Optional): The column fromReferencedTablewhose value should be stored in theFKColumnName. Defaults to the primary key ofReferencedTable.ReferencedColumn(Optional): The column inReferencedTablethatValueColumncorresponds to (usually the same asValueColumnor the PK). Defaults toValueColumnor the PK.
- Attributes:
ActionButton.<ButtonName>(Optional, Multiple): Defines a custom button displayed below the related data tabs. Replace<ButtonName>with a unique name.- Attributes:
Label(Required): The text displayed on the button (e.g.,Label="Run Report").Command(Required): The command or executable to run. Can include placeholders{ColumnName}which will be replaced with the value from the currently selected row. Example:Command="C:\Scripts\ProcessOrder.bat {OrderID} {CustomerName}".RequiresSelection(Optional):TrueorFalse. IfTrue(default), the button is disabled unless a row is selected.SuccessMessage(Optional): A message box to show after the command is launched.
- Warning: Commands are executed via
Process.Start. Ensure commands are safe and consider settingDisableCustomActionExecution=Truein[Global]if untrusted users might modify configuration files.
- Attributes:
RelatedChild.<RelationName>(Optional, Multiple): Defines an explicit relationship to display as a tab, showing child records. Replace<RelationName>with a unique name. Overrides automatic detection for the specified child table/FK.- Attributes:
Label(Required): The text displayed on the tab (e.g.,Label="Orders").ChildTable(Required): The related child table (formatSchema.TableName, e.g.,ChildTable=dbo.Orders).ChildFKColumn(Required): The foreign key column in theChildTablethat references the current table (e.g.,ChildFKColumn=CustomerID).ParentPKColumn(Optional): The primary key column in the current table thatChildFKColumnreferences. Defaults to the single primary key of the current table if omitted. Required if the current table has a composite PK or the FK references a non-PK unique key.ChildFilter(Optional): An additional static SQLWHEREclause condition to apply when querying theChildTable(e.g.,ChildFilter="IsActive = 1"). Warning: This is appended directly to the SQL query; avoid user input or complex logic here to prevent injection risks.
- Attributes:
- Launch: Run
DynamicSqlEditor.exe. - Connect: The application attempts to connect using the configuration. The status bar indicates the connection status.
- Select Table: Use the "Tables" menu. Tables are grouped by schema. Click a table name to open its data view in a new MDI child window.
- Browse Data:
- The top panel shows a grid with the table data.
- Use the paging controls at the bottom of the grid to navigate through pages. Change the page size using the dropdown.
- Click column headers to sort data (click again to toggle direction).
- Use the "Filter" dropdown (if available) to apply pre-defined filters. Some filters may prompt for input.
- View/Edit Details:
- Select a row in the grid.
- The bottom panel ("Details" tab) shows the data for the selected row in an editable form.
- Fields might be read-only based on configuration or schema (PKs, computed columns, etc.).
- Make changes to the editable fields. An asterisk (
*) appears in the window title indicating unsaved changes. - Use the "Is Null" checkbox for nullable fields.
- Use ComboBoxes for foreign key lookups.
- CRUD Actions (Detail Panel):
- New: Clears the detail form to enter a new record. Disables grid/paging/filtering.
- Save: Saves the current changes (for a new or modified record). Enabled only when changes are pending. Performs concurrency check if applicable.
- Delete: Deletes the currently selected record (prompts for confirmation). Performs concurrency check if applicable.
- Refresh: Reloads the data for the current page, discarding any pending changes in the detail view if prompted.
- Related Data: Click other tabs in the bottom panel (if any) to view data from related tables linked to the currently selected record in the main grid.
- Custom Actions: Click custom buttons (if configured) below the tabs to execute external commands, potentially using data from the selected row.
- Window Management: Use the "Window" menu to arrange or close MDI child windows.
- Closing: Closing a data view window or the main application will prompt to save unsaved changes.
- UI Layer (
DynamicSqlEditor.UI):- Contains WinForms Forms (
MainForm,DataViewForm), User Controls (PagingControl,NullableDateTimePicker), Dialogs (FilterInputDialog), and Builders (DetailFormBuilder,FilterUIBuilder, etc.). - Responsible for presenting data and handling user interaction.
- Builders dynamically create UI elements based on configuration and schema.
- Contains WinForms Forms (
- Core Layer (
DynamicSqlEditor.Core):- Manages application state (
StateManager). - Handles data view logic (
DataViewManager- paging, sorting, filtering). - Orchestrates CRUD operations (
CrudManager).
- Manages application state (
- DataAccess Layer (
DynamicSqlEditor.DataAccess):- Handles direct database interaction (
DatabaseManager). - Provides data paging implementation (
DataPager). - Builds SQL queries (
QueryBuilder). - Manages concurrency checks (
ConcurrencyHandler).
- Handles direct database interaction (
- Schema Layer (
DynamicSqlEditor.Schema):- Retrieves database metadata (
SchemaProvider). - Filters schema based on configuration (
SchemaFilter). - Defines schema object models (
TableSchema,ColumnSchema, etc.).
- Retrieves database metadata (
- Configuration Layer (
DynamicSqlEditor.Configuration):- Loads and parses
.dslfiles (ConfigurationManager,DslParser). - Defines configuration object models (
AppConfig,TableConfig,*Definition, etc.).
- Loads and parses
- Common Layer (
DynamicSqlEditor.Common):- Provides shared utilities like logging (
FileLogger), constants (Constants), control creation helpers (ControlFactory), and global error handling (GlobalExceptionHandler).
- Provides shared utilities like logging (
- Complex Data Types: Limited support for displaying/editing complex SQL types (XML, spatial types,
sql_variant, UDTs). They are generally hidden by default. - Performance: Performance on tables with a very large number of columns or rows, or complex custom queries, might degrade. Paging helps with rows, but wide tables can still be slow to render.
- DSL Parser: The DSL parser is basic. It might not handle complex quoting or escaping scenarios robustly.
- SQL Injection Risk:
CustomSelectQuery,ActionButton.Command, andRelatedChild.ChildFilterallow embedding configured SQL/commands. While placeholders help for action buttons, care must be taken to avoid SQL injection vulnerabilities, especially if configuration files can be modified by non-administrators. Consider usingDisableCustomActionExecution=True. - Concurrency: Basic timestamp/rowversion concurrency is supported. More complex scenarios (e.g., logical deletes, multi-user edits without timestamps) are not handled.
- Schema Query Compatibility: Schema queries are written for SQL Server's
INFORMATION_SCHEMAandsysobjects. Compatibility with other database systems is not guaranteed. - No IntelliSense for DSL: Configuration is done in plain text files.
(Placeholder - Add guidelines if contributions are accepted) Contributions are welcome! Please follow standard practices like creating issues for bugs or feature requests and submitting pull requests for changes.
(Placeholder - Add license information, e.g., MIT, Apache 2.0) This project is licensed under the [Your License Name] License - see the LICENSE.md file for details.