# 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.

```filetree
MyApp.sln
├── MyApp.DB/                          <- class library for DB models
│   ├── MyApp.DB.csproj
│   ├── socigy.json                    <- migration and codegen config (project root)
│   ├── Users/
│   │   ├── User.cs                    <- [Table] partial class
│   │   └── UserRole.cs                <- [Flags] enum mapped with [Table]
│   ├── Products/
│   │   └── Product.cs
│   └── Socigy/
│       └── Procedures/                <- .sql files for procedure mapping
│           └── GetUserById.sql
└── MyApp.API/
    └── MyApp.API.csproj
```

---

## The DB project file

The DB class library references `Socigy.OpenSource.DB`. If you use [Procedure mapping](/database/0.3.2/advanced/procedure-mapping), declare `.sql` files as `<AdditionalFiles>` so the source generator can read them at build time:

```xml
<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>
```

> **NOTE** The `AdditionalFiles` glob is required only if you use procedure mapping. Omit it for projects that use table-based queries alone.

> **TIP** Setting `<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:

1. **Decorated with `[Table("table_name")]`**, which tells the generator the SQL table this class represents.
2. **Declared `partial`**, which lets the generator add members (query methods, `IDbTable` implementation, column constants) in a companion generated file.

```csharp
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.

> **NOTE** Schema attributes and the `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:

```plaintext
obj/{Configuration}/net{version}/generated/Socigy.OpenSource.DB.SourceGenerator/Socigy.OpenSource.DB.SourceGenerator.Program/
```

For example, a `Debug` build targeting `net10.0` uses:

```plaintext
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 `IDbTable` interface 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](/database/0.3.2/core-concepts/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:

```csharp
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`:

```plaintext
obj/
bin/
```

The generator recreates all output on the next `dotnet build`, so nothing is lost by excluding it.
