A Roslyn source generator that reads SQL files at compile time and generates a C# class with const string values for each SQL file content. This gives you the best of both worlds, direct C# constants but a SQL file with SQL syntax support with formatting and suggestions applicable to SQL without requiring special IDE integration.
dotnet add package ConstantSQL
ConstantSQL supports two ways to organize your SQL files:
One SQL query per file - the constant is named after the file:
GetUsers.sql
:
SELECT * FROM Users WHERE Active = 1
Generated code:
public const string GetUsers = @"SELECT * FROM Users WHERE Active = 1";
Multiple named SQL queries in a single file using -- @name:
markers:
UserQueries.sql
:
-- @name: GetActiveUsers
SELECT Id, Name, Email
FROM Users
WHERE Active = 1;
-- @name: GetUserById
SELECT Id, Name, Email, CreatedDate
FROM Users
WHERE Id = @UserId;
-- @name: UpdateUserEmail
UPDATE Users
SET Email = @Email, ModifiedDate = GETUTCDATE()
WHERE Id = @UserId;
Generated code:
public const string GetActiveUsers = @"SELECT Id, Name, Email
FROM Users
WHERE Active = 1;";
public const string GetUserById = @"SELECT Id, Name, Email, CreatedDate
FROM Users
WHERE Id = @UserId;";
public const string UpdateUserEmail = @"UPDATE Users
SET Email = @Email, ModifiedDate = GETUTCDATE()
WHERE Id = @UserId;";
using ConstantSQL.SqlFiles;
// From single-statement file
var query1 = Queries.GetUsers;
// From multi-statement file
var query2 = Queries.GetActiveUsers;
var query3 = Queries.UpdateUserEmail;
By default, the source generator looks for all *.sql
files in your project:
<ItemGroup>
<!-- Default: includes all SQL files -->
<SqlFiles Include="**\*.sql" />
</ItemGroup>
- ✅ Compile-time SQL file processing
- ✅ Strongly-typed access to SQL queries
- ✅ IntelliSense support
- ✅ No runtime file I/O
- ✅ Automatic handling of special characters and escaping
- ✅ Support for files with duplicate names (with automatic suffixing)
- ✅ Single-statement files (one query per file)
- ✅ Multi-statement files (multiple named queries per file using
-- @name:
markers)
Given a SQL file GetActiveUsers.sql
:
SELECT Id, Name, Email
FROM Users
WHERE Active = 1
ORDER BY Name
The generator creates:
namespace ConstantSQL.SqlFiles
{
public static class Queries
{
public const string GetActiveUsers = @"SELECT Id, Name, Email
FROM Users
WHERE Active = 1
ORDER BY Name";
}
}
Apache 2.0