Skip to content

Commit 6c8cc01

Browse files
committed
- checkpoint: streamlined uow, connection scope and transactions.
1 parent 1611468 commit 6c8cc01

84 files changed

Lines changed: 1633 additions & 1911 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ All connection types live in the `ActiveForge` namespace, so a single `using Act
2727
### 🗂 Entities & Mapping
2828
- **Active Record pattern** — entities carry both data and persistence behaviour; no separate repository class required
2929
- **Type-safe field wrappers**`TString`, `TInt`, `TDecimal`, `TPrimaryKey`, `TForeignKey`, and 25+ more; each tracks null/loaded state and supports implicit conversion
30-
- **Polymorphic mapping** — map abstract base types to concrete subtypes via `FactoryBase`
30+
- **Polymorphic mapping** — map abstract base types to concrete subtypes via `BaseFactory`
3131
- **Custom field mappers** — implement `IDBFieldMapper` for non-standard type conversions
3232
- **Field encryption** — transparent encrypt/decrypt via `[Encrypted]` attribute
3333

@@ -40,12 +40,12 @@ All connection types live in the `ActiveForge` namespace, so a single `using Act
4040

4141
### 💾 Data Management
4242
- **Transactions** — manual nested transactions via `BeginTransaction` / `CommitTransaction` / `RollbackTransaction`
43-
- **Unit of Work**`IUnitOfWork`, `UnitOfWorkBase`, provider-specific implementations, `With.Transaction`, `[Transaction]` attribute, Castle DynamicProxy interceptor. `[Transaction]` wraps a service method in a `IUnitOfWork` transaction via Castle DynamicProxy; combine with `[ConnectionScope]` for the full open → begin → commit → close lifecycle
44-
- **Connection-level lifecycle** — set `conn.UnitOfWork = uow` once; every write operation (`Insert`, `Update`, `Delete`, `ProcessActionQueue`, `ExecStoredProcedure`) automatically opens the connection, begins a transaction, commits, and closes — no proxy required; coordinates transparently with `[ConnectionScope]` via `IsOpen`. `[ConnectionScope]` — marks service methods/classes where the `DataConnection` is opened before and closed after; nested calls share one connection via `IsOpen` state.
43+
- **Unit of Work**`IUnitOfWork`, `BaseUnitOfWork`, provider-specific implementations (`SqlServerUnitOfWork`, `PostgreSQLUnitOfWork`, `MongoUnitOfWork`, `SQLiteUnitOfWork`), `With.Transaction`, `[Transaction]` attribute, Castle DynamicProxy interceptor. `[Transaction]` wraps a service method in an `IUnitOfWork` transaction; the UoW opens the connection before the first `CreateTransaction()` call and closes it after the outermost commit or rollback.
44+
- **Connection-level lifecycle** — set `conn.UnitOfWork = uow` once; every write operation (`Insert`, `Update`, `Delete`, `ProcessActionQueue`, `ExecStoredProcedure`) automatically opens the connection, begins a transaction, commits, and closes — no proxy required.
4545
- **Action queue** — batch operations via `QueueForInsert` / `QueueForUpdate` / `QueueForDelete``ProcessActionQueue`
4646

4747
### 🌐 DI & Service Proxy Integration
48-
- **Auto-scan registration**`AddActiveForgeSqlServer(...).AddServices(assembly)` discovers all `IService` implementations and registers them as interface-proxied scoped services in one call. `IService` marker — implement on any service class for automatic discovery and proxy registration. `IActiveForgeBuilder` — fluent builder returned by all `AddTurquoise*` methods; chain `.AddServices()`, `.AddService<I, T>()` for granular control.
48+
- **Auto-scan registration**`AddActiveForgeSqlServer(...).AddServices(assembly)` discovers all `IService` implementations and registers them as interface-proxied scoped services in one call. `IService` marker — implement on any service class for automatic discovery and proxy registration. `IActiveForgeBuilder` — fluent builder returned by all `AddActiveForge*` methods; chain `.AddServices()`, `.AddService<I, T>()` for granular control.
4949

5050
---
5151

@@ -213,7 +213,6 @@ open → begin → commit → close with no virtual methods or framework couplin
213213

214214
```csharp
215215
using ActiveForge;
216-
using ActiveForge.Attributes;
217216
using ActiveForge.Transactions;
218217

219218
// ── Interface (consumed by controllers / other services)
@@ -229,11 +228,9 @@ public class OrderService : IOrderService, IService
229228
private readonly DataConnection _conn;
230229
public OrderService(DataConnection conn) { _conn = conn; }
231230

232-
[ConnectionScope] // connection opens before, closes after
233231
public Order GetById(int id) { ... }
234232

235-
[ConnectionScope] // connection opens
236-
[Transaction] // transaction wraps the body
233+
[Transaction] // opens connection, begins tx, commits/rolls back, closes connection
237234
public void Ship(int orderId)
238235
{
239236
var order = new Order(_conn);
@@ -285,11 +282,9 @@ With.Transaction(uow, () =>
285282
| [Getting Started](docs/getting-started.md) | Step-by-step tutorial |
286283
| [Field Types](docs/field-types.md) | All `TField` types and their operators |
287284
| [Query Builder](docs/query-builder.md) | Composing WHERE, ORDER BY, and pagination |
288-
| [Transactions](docs/transactions.md) | Manual transaction and action queue patterns |
289-
| [Unit of Work](docs/unit-of-work.md) | `IUnitOfWork`, `With.Transaction`, Castle interceptor |
285+
| [Transactions & DI](docs/transactions-and-di.md) | Manual transactions, `IUnitOfWork`, `With.Transaction`, `[Transaction]` interceptor, DI service proxies |
290286
| [LINQ Querying](docs/linq-querying.md) | `conn.Query<T>()` LINQ support |
291287
| [Field Subsets](docs/field-subsets.md) | Partial fetches and partial updates |
292-
| [DI & Service Proxies](docs/di-service-proxies.md) | `AddActiveForge*`, `AddActiveForgeService<T>`, `[ConnectionScope]`, `ActiveForgeServiceFactory` |
293288
| [Advanced](docs/advanced.md) | Encryption, custom mappers, polymorphism |
294289
| [**Wiki**](docs/wiki.md) | Comprehensive reference — all concepts with examples |
295290

@@ -306,7 +301,7 @@ ActiveForge/
306301
│ │ ├── Fields/ ← TString, TInt, TDecimal, ... (25+ types)
307302
│ │ ├── Linq/ ← LINQ query support
308303
│ │ ├── Query/ ← QueryTerm, SortOrder, EqualTerm, ...
309-
│ │ └── Transactions/ ← IUnitOfWork, UnitOfWorkBase, With, ConnectionScopeInterceptor,
304+
│ │ └── Transactions/ ← IUnitOfWork, BaseUnitOfWork, With,
310305
│ │ TransactionInterceptor, ActiveForgeServiceFactory
311306
│ ├── ActiveForge.SqlServer/ ← SQL Server provider
312307
│ │ ├── Adapters/ ← SqlAdapterCommand/Connection/Reader/Transaction

docs/advanced.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ public TString Metadata = new TString();
6868
## Polymorphic Type Mapping
6969

7070
When you have an abstract base entity and multiple concrete subtypes (table-per-hierarchy
71-
or table-per-type), register the mapping in your `FactoryBase`:
71+
or table-per-type), register the mapping in your `BaseFactory`:
7272

7373
```csharp
74-
public class AppFactory : FactoryBase
74+
public class AppFactory : BaseFactory
7575
{
7676
protected override void CreateTypeMap()
7777
{
@@ -142,7 +142,7 @@ var results = conn.ExecSQL(template,
142142
"SELECT * FROM Products WHERE CreatedAt > @since",
143143
new Dictionary<string, object> { { "@since", DateTime.Today.AddDays(-7) } });
144144

145-
// Returns a ReaderBase for low-level access
145+
// Returns a BaseReader for low-level access
146146
using var reader = conn.ExecSQL("SELECT COUNT(*) FROM Products");
147147
reader.Read();
148148
int count = (int)reader.GetValue(0);

0 commit comments

Comments
 (0)