Applied via `dotnet format analyzers --diagnostics CA1822 --severity info`. 12 files touched. The fixer also updated internal callers in tests to use the type-name form (e.g. `gen.Method(x)` -> `Generator.Method(x)`); build and full test suite remain green. BREAKING CHANGE: two public methods become static and therefore can no longer be invoked through an instance reference by external consumers: - Strata.SqlTools.Markdown.LinqToSql.QueryBreakdownGenerator.GenerateMethodChainDiagram - Strata.SqlTools.Markdown.LinqToSql.SqlStatementGenerator.GenerateLinqPipelineDiagram Both are stateless utility methods on Generator classes — the static form is the correct shape; the only callers in this repo already used the type-name form. External code should change `gen.GenerateMethodChainDiagram(...)` to `QueryBreakdownGenerator.GenerateMethodChainDiagram(...)`. All other CA1822 hits in this commit are on private/protected members (no public-surface impact). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
117 lines
4.5 KiB
C#
117 lines
4.5 KiB
C#
|
|
using Strata.SqlTools.SqlBreakdown.Interfaces;
|
|
using Strata.SqlTools.SqlBreakdown.Interfaces.QueryEngine;
|
|
|
|
namespace Strata.SqlTools.Markdown.LinqToSql;
|
|
|
|
/// <summary>
|
|
/// Generates Mermaid diagrams for LINQ to SQL statements, including sequence diagrams
|
|
/// for statement execution flow and entity-relationship diagrams.
|
|
/// </summary>
|
|
public class SqlStatementGenerator
|
|
{
|
|
private readonly SqlServer.SqlStatementGenerator _baseGenerator;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the SqlStatementGenerator class.
|
|
/// </summary>
|
|
public SqlStatementGenerator()
|
|
{
|
|
_baseGenerator = new SqlServer.SqlStatementGenerator();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generates a Mermaid sequence diagram showing LINQ to SQL statement execution flow.
|
|
/// </summary>
|
|
/// <param name="sqlBreakdown">The LINQ to SQL breakdown object.</param>
|
|
/// <param name="title">Optional title for the diagram.</param>
|
|
/// <returns>A string containing the Mermaid sequence diagram markdown.</returns>
|
|
public string GenerateSequenceDiagram(ISqlBreakdown sqlBreakdown, string? title = null)
|
|
{
|
|
return _baseGenerator.GenerateSequenceDiagram(sqlBreakdown, title);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generates a Mermaid entity-relationship diagram from a SQL breakdown.
|
|
/// </summary>
|
|
/// <param name="sqlBreakdown">The SQL breakdown containing query information.</param>
|
|
/// <param name="title">Optional title for the diagram.</param>
|
|
/// <returns>A string containing the Mermaid ER diagram markdown.</returns>
|
|
public string GenerateEntityRelationshipDiagram(ISqlBreakdown sqlBreakdown, string? title = null)
|
|
{
|
|
//Extract table names from breakdown - just use FROM clause for now
|
|
var queryBreakdown = sqlBreakdown as IQueryBreakdown;
|
|
var tableNames = new List<string>();
|
|
|
|
var fromClauseText = queryBreakdown?.FromClause?.ToString();
|
|
if (!string.IsNullOrWhiteSpace(fromClauseText))
|
|
{
|
|
tableNames.Add(fromClauseText);
|
|
}
|
|
|
|
return _baseGenerator.GenerateEntityRelationshipDiagram(tableNames, title);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generates a diagram showing LINQ execution pipeline from a SQL breakdown.
|
|
/// </summary>
|
|
/// <param name="queryBreakdown">The query breakdown containing query information.</param>
|
|
/// <param name="title">Optional title for the diagram.</param>
|
|
/// <returns>A string containing the Mermaid diagram markdown.</returns>
|
|
public static string GenerateLinqPipelineDiagram(IQueryBreakdown queryBreakdown, string? title = null)
|
|
{
|
|
var sb = new System.Text.StringBuilder();
|
|
|
|
if (!string.IsNullOrWhiteSpace(title))
|
|
{
|
|
sb.AppendLine($"### {title}");
|
|
sb.AppendLine();
|
|
}
|
|
|
|
sb.AppendLine("```mermaid");
|
|
sb.AppendLine("sequenceDiagram");
|
|
sb.AppendLine(" participant Client as Client Application");
|
|
sb.AppendLine(" participant LINQ as LINQ Provider");
|
|
sb.AppendLine(" participant ET as Expression Tree");
|
|
sb.AppendLine(" participant SQL as SQL Generator");
|
|
sb.AppendLine(" participant DB as Database");
|
|
sb.AppendLine();
|
|
sb.AppendLine(" Client->>LINQ: LINQ Query");
|
|
sb.AppendLine(" activate LINQ");
|
|
|
|
// Check if there's a WHERE clause
|
|
var whereClause = queryBreakdown.WhereClause?.Clause;
|
|
if (!string.IsNullOrWhiteSpace(whereClause))
|
|
{
|
|
sb.AppendLine(" LINQ->>ET: Where Predicate");
|
|
sb.AppendLine(" activate ET");
|
|
}
|
|
|
|
// Check if there's a custom SELECT
|
|
var selectClause = queryBreakdown.SelectClause?.Clause;
|
|
if (!string.IsNullOrWhiteSpace(selectClause) && selectClause.Trim() != "*")
|
|
{
|
|
sb.AppendLine(" LINQ->>ET: Select Projection");
|
|
if (string.IsNullOrWhiteSpace(whereClause))
|
|
{
|
|
sb.AppendLine(" activate ET");
|
|
}
|
|
}
|
|
|
|
sb.AppendLine(" ET->>SQL: Expression Tree");
|
|
sb.AppendLine(" deactivate ET");
|
|
sb.AppendLine(" SQL->>DB: Generate SQL");
|
|
sb.AppendLine(" activate DB");
|
|
sb.AppendLine(" DB-->>SQL: Result Set");
|
|
sb.AppendLine(" deactivate DB");
|
|
sb.AppendLine(" SQL-->>LINQ: Mapped Objects");
|
|
sb.AppendLine(" LINQ-->>Client: IEnumerable Result");
|
|
sb.AppendLine(" deactivate LINQ");
|
|
sb.AppendLine("```");
|
|
sb.AppendLine();
|
|
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|