Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
## Purpose

This repository generates human-readable HTML documentation for Microsoft SQL Server databases (2005+).
This file gives pragmatic, repo-specific guidance for an AI coding assistant to be productive quickly.

## Quick Tasks

- **Build:** run `dotnet build` at the repository root (solution file `SqlServerDatabaseDocumentationGenerator.sln`). VS2019/VS2022 can also be used for .NET Framework builds.
- **Run Console Example:** edit `DocumentationGeneratorConsole/Program.cs` to change the connection string, then run the Console project; it writes `database.html` to the current directory.
- **Run GUI:** `DocumentationGeneratorApplication` is a WinForms app (MainForm.cs). Launch from Visual Studio to use the interactive connection-string dialog.

## Key Components (big picture)

- **Entry projects:**
- `DocumentationGeneratorApplication/` — WinForms GUI, interactive connection string and save dialog (MainForm.cs, FrmConnectionString.cs).
- `DocumentationGeneratorConsole/` — small console runner (Program.cs), currently uses a hard-coded `connStr` and writes `database.html`.
- `SqlServerDatabaseDocumentationGenerator/` — core library: Document, Inspection, Model, Utility, and DesignIssue folders.

- **Core flow:**
1. `DatabaseInspector` (in `Inspection/`) reads metadata from SQL Server (schemas, tables, views, columns, routines) into Model objects.
2. `DatabaseHtmlDocumentGenerator` (in `Document/`) converts `Model.Database` to an HTML document using an internal `HtmlTextWriter` fallback.
3. Output is an HTML file (Bootstrap CSS included inline).

## Repo-specific patterns & conventions

- Database object descriptions are pulled from the extended property named `MS_Description` (expect code to refer to this).
- The `Document/DatabaseHtmlDocumentGenerator.cs` contains a self-contained fallback for `System.Web.UI.HtmlTextWriter` — careful when adding System.Web references or testing on environments without it.
- Inspector classes follow the pattern `*Inspector.cs` (e.g., `TableInspector.cs`, `SchemaInspector.cs`) and populate POCOs in `Model/` — prefer working through the inspector methods to change how metadata is collected.

## Important files to inspect/edit

- `SqlServerDatabaseDocumentationGenerator/Document/DatabaseHtmlDocumentGenerator.cs` — main HTML generation; contains the app version and base CSS.
- `SqlServerDatabaseDocumentationGenerator/Inspection/DatabaseInspector.cs` — orchestrates other inspectors and exposes `GetDatabaseMetaData()`.
- `DocumentationGeneratorConsole/Program.cs` — minimal runnable example; useful for automation and CI.
- `DocumentationGeneratorApplication/` — UI-specific code (WinForms): `MainForm.cs`, `FrmConnectionString.cs`.
- `SqlServerDatabaseDocumentationGenerator.sln` and `.vscode/tasks.json` (task `build`) — canonical build targets.

## Building, testing, and debugging notes

- The solution targets .NET Framework 4.8 (Readme states 4.8, compatible with 4.5+). Use Visual Studio for WinForms debugging.
- To build from terminal (cross-machine):

```
dotnet build "SqlServerDatabaseDocumentationGenerator.sln"
```

- The console project currently hardcodes a connection string — update `Program.cs` or add CLI arg parsing before running in non-dev environments.
- Output HTML (example) is at `AdventureWorks-example.html` in the repo root — use it as a sample for layout and expected content.

## Integration & external dependencies

- Expects a reachable Microsoft SQL Server instance and valid connection string (Integrated or SQL auth).
- Third-party code lives under `third-party/` (e.g., `BeTimvwFramework`); inspect those for license/compat issues.

## Coding guidance for PRs

- Preserve public model shapes in `Model/` where possible — many components (inspectors, document generator) rely on these POCOs.
- When modifying HTML output, edit `DatabaseHtmlDocumentGenerator.cs`. There is an inline `baseCss` and bootstrap usage; search for `baseCss` in that file.
- Avoid introducing a hard dependency on `System.Web` — the repo intentionally includes a lightweight fallback. If you add System.Web references, update project files and ensure builds still succeed on CI/targets.

## Helpful searches/examples

- To find metadata collection code: search for `GetDatabaseMetaData`, `DatabaseInspector`, or names under `Inspection/`.
- To find where descriptions are read: search for `MS_Description` or `ExtendedProperty` string patterns.

## If you need more

If any part of the flow or environment is unclear (e.g., which project is used in a specific CI or how tests are run), tell me which area to expand and I will update this file with concrete commands and examples.
14 changes: 14 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch DocumentationGeneratorConsole (exe)",
"type": "coreclr",
"request": "launch",
"program": "${workspaceFolder}/DocumentationGeneratorConsole/bin/Debug/net40/DocumentationGeneratorConsole.exe",
"args": [],
"cwd": "${workspaceFolder}/DocumentationGeneratorConsole",
"console": "internalConsole"
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"dotnet.preferCSharpExtension": true
}
17 changes: 17 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}",
"/property:GenerateFullPaths=true",
"/consoleLoggerParameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}
Binary file not shown.
54 changes: 6 additions & 48 deletions DbDocGenerator/DbDocGenerator.csproj
Original file line number Diff line number Diff line change
@@ -1,58 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{77C675D0-B954-45F0-AAD8-E3880829EA02}</ProjectGuid>
<TargetFramework>net45</TargetFramework>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DbDocGenerator</RootNamespace>
<AssemblyName>DbDocGenerator</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

</Project>
Original file line number Diff line number Diff line change
@@ -1,123 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5FF70C2D-FDE3-47F6-A95C-605C98CE1996}</ProjectGuid>
<TargetFramework>net48</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>net.datacowboy.DocumentationGeneratorApplication</RootNamespace>
<AssemblyName>DocumentationGeneratorApplication</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Data.Linq" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FrmConnectionString.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FrmConnectionString.Designer.cs">
<DependentUpon>FrmConnectionString.cs</DependentUpon>
</Compile>
<Compile Include="FrmObjectsWithoutDescription.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FrmObjectsWithoutDescription.Designer.cs">
<DependentUpon>FrmObjectsWithoutDescription.cs</DependentUpon>
</Compile>
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="third-party\BeTimvwFramework\Collections\Generic\PropertyComparer.cs" />
<Compile Include="third-party\BeTimvwFramework\ComponentModel\FilterList.cs" />
<Compile Include="third-party\BeTimvwFramework\ComponentModel\PropertyDescriptorHelper.cs" />
<Compile Include="third-party\BeTimvwFramework\ComponentModel\SortableBindingList.cs" />
<EmbeddedResource Include="FrmConnectionString.resx">
<DependentUpon>FrmConnectionString.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FrmObjectsWithoutDescription.resx">
<DependentUpon>FrmObjectsWithoutDescription.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>

<ItemGroup>
<None Include="App.config" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SqlServerDatabaseDocumentationGenerator\SqlServerDatabaseDocumentationGenerator.csproj">
<Project>{68bb69bf-a89e-4a81-b2b7-160ace34e0f7}</Project>
<Name>SqlServerDatabaseDocumentationGenerator</Name>
</ProjectReference>
<ProjectReference Include="..\SqlServerDatabaseDocumentationGenerator\SqlServerDatabaseDocumentationGenerator.csproj" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

</Project>
3 changes: 3 additions & 0 deletions DocumentationGeneratorApplication/FrmConnectionString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ public FrmConnectionString(string connectionString="")
catch (Exception ex)
{
//TODO: tell user something wrong in initial connection string
MessageBox.Show(String.Format("Unable to parse initial connection string:\n{0}", ex.Message), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
builder = new SqlConnectionStringBuilder();

}

if (!String.IsNullOrWhiteSpace(builder.DataSource))
Expand Down
28 changes: 25 additions & 3 deletions DocumentationGeneratorApplication/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,32 @@ private string getConnectionStringFromAppConfig()
string connString = null;


var config = ConfigurationManager.ConnectionStrings["default"];
if (config != null)
try
{
// Try to access ConfigurationManager via reflection so the code compiles
// even when System.Configuration assembly is not referenced (e.g. .NET Core).
var cmType = Type.GetType("System.Configuration.ConfigurationManager, System.Configuration.ConfigurationManager")
?? Type.GetType("System.Configuration.ConfigurationManager");
if (cmType != null)
{
var connectionStringsProp = cmType.GetProperty("ConnectionStrings", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
var connectionStrings = connectionStringsProp?.GetValue(null);
if (connectionStrings != null)
{
// indexer "Item" with key
var indexer = connectionStrings.GetType().GetProperty("Item");
var config = indexer?.GetValue(connectionStrings, new object[] { "default" });
if (config != null)
{
var connStringProp = config.GetType().GetProperty("ConnectionString");
connString = connStringProp?.GetValue(config) as string;
}
}
}
}
catch
{
connString = config.ConnectionString;
// ignore any reflection failures and return null
}


Expand Down
Loading