# Project structure

Recommended layout for a project that uses Socigy.OpenSource.DB, including 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                <- [FlaggedEnum] enum
│   ├── 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.1.83/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.1.83" />
  </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 only required if you use procedure mapping. It can be omitted for projects that only use table-based queries.

> **TIP** Setting `<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>` copies generated files from `obj/Generated/` 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")]`** — tells the generator which SQL table this class represents.
2. **Declared `partial`** — allows the generator to add members (query methods, `IDbTable` implementation, `Columns` constants) in a companion generated file.

```csharp
// Correct — generator will augment this class
[Table("products")]
public partial class Product { ... }

// Wrong — generator will skip this class; no query methods will be emitted
[Table("products")]
public class Product { ... }
```

The class can be in any namespace. Nesting inside another class is not supported.

---

## Generated files

The source generator writes one `.g.cs` file per annotated class. The files are placed 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`.

You 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)

---

## Static column name constants

The generator emits a `{PropertyName}ColumnName` constant directly 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 are useful when building dynamic SQL fragments or logging query details without hard-coding string literals.

---

## Keeping obj/ out of source control

Generated files should not be committed. Add `obj/` to your `.gitignore`:

```plaintext
obj/
bin/
```

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