Project structure
Recommended layout for a project that uses Socigy.OpenSource.DB, covering the DB class library, SQL procedure files, and generated output.
Recommended layout
There are no hard requirements on directory structure, but isolating DB models in a dedicated class library is strongly recommended. It lets multiple consumers (API, background workers, test projects) reference the same typed models without pulling in unrelated dependencies.
The DB project file
The DB class library references Socigy.OpenSource.DB. If you use Procedure mapping, declare .sql files as <AdditionalFiles> so the source generator can read them at build time:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Socigy.OpenSource.DB" Version="0.3.2" />
</ItemGroup>
<!-- Only needed for procedure mapping -->
<ItemGroup>
<AdditionalFiles Include="Socigy\Procedures\**\*.sql" />
</ItemGroup>
<!-- Optionally emit generated files into the project tree for inspection -->
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
</Project>AdditionalFiles glob is required only if you use procedure mapping. Omit it for projects that use table-based queries alone.<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> writes generated files into $(IntermediateOutputPath)/generated/ so IDEs can index them more reliably. It is optional.Model class requirements
Every class that maps to a database table must meet two conditions:
- Decorated with
[Table("table_name")], which tells the generator the SQL table this class represents. - Declared
partial, which lets the generator add members (query methods,IDbTableimplementation, column constants) in a companion generated file.
using Socigy.OpenSource.DB.Attributes;
// Correct: the generator augments this class
[Table("products")]
public partial class Product { /* ... */ }
// Wrong: the generator skips this class, no query methods are emitted
[Table("products")]
public class Product { /* ... */ }The class can live in any namespace. Nesting inside another class is not supported.
DbDefaults constants resolve from Socigy.OpenSource.DB.Attributes. The only attribute outside that namespace is [Nullable], in Socigy.OpenSource.DB.Core.Attributes.Generated files
The source generator writes one .g.cs file per annotated class under the intermediate output path:
obj/{Configuration}/net{version}/generated/Socigy.OpenSource.DB.SourceGenerator/Socigy.OpenSource.DB.SourceGenerator.Program/For example, a Debug build targeting net10.0 uses:
obj/Debug/net10.0/generated/Socigy.OpenSource.DB.SourceGenerator/Socigy.OpenSource.DB.SourceGenerator.Program/To have the IDE index these files reliably, add <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> to your .csproj.
Never edit these files directly, they are recreated on every build. Each generated file contains:
- The
IDbTableinterface implementation (GetTableName(),GetColumns(),GetPrimaryColumns(),GetColumn(),GetDbColumnName()). - Static factory methods:
Query(),Insert(),Update(),Delete(). - Instance shortcut methods:
user.Insert(),user.Update(),user.Delete(). - Column name constants (see below).
When a databaseName is configured, the generator also emits the database context (IAppDb / AppDbContext), the per-table sets, and the DI extensions. See Database context.
Static column name constants
The generator emits a {PropertyName}ColumnName constant on each model class for every mapped property, using the snake_case database column name:
User.UsernameColumnName // => "username"
User.CreatedAtColumnName // => "created_at"
User.IdColumnName // => "id"These help when building dynamic SQL fragments or logging query details without hard-coding string literals.
Keeping obj/ out of source control
Generated files should never be committed. Add obj/ to your .gitignore:
obj/
bin/The generator recreates all output on the next dotnet build, so nothing is lost by excluding it.