Forge.Repository.Oracle 10.0.1

dotnet add package Forge.Repository.Oracle --version 10.0.1
                    
NuGet\Install-Package Forge.Repository.Oracle -Version 10.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Forge.Repository.Oracle" Version="10.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Forge.Repository.Oracle" Version="10.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Forge.Repository.Oracle" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Forge.Repository.Oracle --version 10.0.1
                    
#r "nuget: Forge.Repository.Oracle, 10.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Forge.Repository.Oracle@10.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Forge.Repository.Oracle&version=10.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Forge.Repository.Oracle&version=10.0.1
                    
Install as a Cake Tool

Forge.Repository

A flexible, database-agnostic repository pattern implementation for .NET 10 using Entity Framework Core. Forge.Repository provides a comprehensive abstraction layer for data access with support for SQL Server, PostgreSQL, MySQL, and Oracle databases.

Table of Contents

Overview

Forge.Repository is a robust repository pattern implementation built on top of Entity Framework Core 10.*. It abstracts database operations and provides a clean, fluent interface for data access operations. The library supports both synchronous and asynchronous operations, with full support for cancellation tokens and transaction management.

Key Benefits

  • Database Agnostic: Write once, deploy to multiple database engines
  • Async First: Built with async/await patterns for scalable applications
  • Type Safe: Full support for generic repositories with compile-time type checking
  • Unit of Work Pattern: Coordinate multiple operations within a single transaction
  • Performance Tuned: Built-in support for connection pooling and retry logic
  • Auditable: Built-in support for tracking entity changes with timestamps and user information
  • Extensible: Easy to extend and customize for specific application needs

Features

Core Features

  • Generic Repository Pattern: IRepositoryAsync<TEntity> interface for CRUD operations
  • Unit of Work Pattern: IUnitOfWork for coordinating multiple repository operations
  • Async Operations: Full support for async/await programming model with cancellation tokens
  • Criteria-Based Queries: Advanced querying with custom criteria objects
  • Bulk Operations: Methods for adding, updating, and removing multiple entities
  • Raw SQL Support: Execute raw SQL queries and commands with full parameterization support
  • Change Tracking: Access tracked entities through the change tracker
  • Lazy Loading: Optional lazy loading of related entities through proxies
  • Connection Pooling: Built-in support for connection pool configuration
  • Retry Logic: Automatic retry policies for transient failures
  • Soft Deletes: Support for auditable entities with soft delete capabilities

Advanced Features

  • Custom Criteria Objects: ICriteriaAsync<TEntity>, ICriteriaSingleAsync<TEntity> for complex queries
  • Foreign Entity Matching: Query related entities through ICriteriaForeignEntity<TEntity, TFEntity>
  • Database Initialization: IDbInitializer interface for migrations and seeding
  • Provider-Specific Tuning: Database-specific optimizations through IDbProviderTuner
  • Enum String Conversion: Automatic enum-to-string conversion for database storage
  • Auditable Models: IAuditableBaseModel for automatic tracking of creation, modification, and deletion

Supported Databases

Forge.Repository supports the following database engines through dedicated NuGet packages:

Database Package Provider
SQL Server Forge.SqlServer Microsoft.Data.SqlClient
PostgreSQL Forge.PostgreSql Npgsql
MySQL Forge.MySql MySqlConnector
Oracle Forge.Oracle Oracle.ManagedDataAccess

Installation

Core Package

dotnet add package Forge.Repository

Database-Specific Packages

Choose the package matching your target database:

# For SQL Server
dotnet add package Forge.SqlServer

# For PostgreSQL
dotnet add package Forge.PostgreSql

# For MySQL
dotnet add package Forge.MySql

# For Oracle
dotnet add package Forge.Oracle

Quick Start

1. Define Your Entity Models

using Forge.Models;

public class Product : AuditableBaseModel
{
    public required string Name { get; set; }
    public required decimal Price { get; set; }
    public string Description { get; set; }
    public int StockQuantity { get; set; }
}

2. Create Your DbContext

using Forge.Repository;
using Microsoft.EntityFrameworkCore;

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) 
        : base(options)
    {
    }

    public DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // Configure your entities
    }
}

3. Register Services (Startup)

// Program.cs - for SQL Server
using Forge.SqlServer;
using Forge.DbTuner;

var builder = WebApplicationBuilder.CreateBuilder(args);

var poolingOptions = new ForgeDbContextPoolingOptions
{
    EnablePooling = true,
    MinPoolSize = 5,
    MaxPoolSize = 20
};

builder.Services.AddForgeRepositorySqlServer<ApplicationDbContext>(
    builder.Configuration.GetConnectionString("DefaultConnection"),
    poolingOptions,
    tuner => tuner
        .SetRetry(3)
        .SetCommandTimeout(30)
        .EnableLazyLoading()
);

var app = builder.Build();
// ... rest of configuration

4. Use the Repository

public class ProductService : IProductService
{
    private readonly IUnitOfWork _unitOfWork;

    public ProductService(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public async Task<IList<Product>> GetAllProductsAsync(CancellationToken cancellationToken)
    {
        var repository = _unitOfWork.GetRepositoryAsync<Product>();
        return await repository.GetAllAsync(cancellationToken);
    }

    public async Task<Product> GetProductByIdAsync(string id, CancellationToken cancellationToken)
    {
        var repository = _unitOfWork.GetRepositoryAsync<Product>();
        return await repository.GetByIdAsync(id, cancellationToken);
    }

    public async Task AddProductAsync(Product product, CancellationToken cancellationToken)
    {
        var repository = _unitOfWork.GetRepositoryAsync<Product>();
        await repository.AddAsync(product, cancellationToken);
        await _unitOfWork.SaveChangesAsync(cancellationToken);
    }
}

Core Concepts

Base Models

Forge provides two base model classes for your entities:

BaseModel

The simplest entity base class with only an Id property.

public abstract class BaseModel : IBaseModel
{
    public virtual required string Id { get; set; }
}
AuditableBaseModel

An extended base class with built-in audit tracking capabilities.

public abstract class AuditableBaseModel : BaseModel, IAuditableBaseModel
{
    public virtual DateTime CreatedOn { get; set; }
    public virtual DateTime ModifiedOn { get; set; }
    public virtual string CreatedBy { get; set; }
    public virtual string ModifiedBy { get; set; }
    public virtual bool IsDeleted { get; set; }

    public virtual void OnCreate()
    {
        CreatedOn = DateTime.UtcNow;
    }

    public virtual void OnUpdate()
    {
        ModifiedOn = DateTime.UtcNow;
    }

    public virtual void OnDelete()
    {
        IsDeleted = true;
        ModifiedOn = DateTime.UtcNow;
    }
}

Repository Pattern

The IRepositoryAsync<TEntity> interface provides the foundation for all data access operations:

public interface IRepositoryAsync<TEntity> where TEntity : class, IBaseModel
{
    // CRUD Operations
    Task AddAsync(TEntity entity, CancellationToken cancellationToken = default);
    Task AddRangeAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default);
    Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
    Task UpdateRangeAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default);
    Task RemoveAsync(TEntity entity, CancellationToken cancellationToken = default);
    Task RemoveRangeAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default);

    // Query Operations
    Task<TEntity> GetByIdAsync(string id, CancellationToken cancellationToken = default);
    Task<IList<TEntity>> GetAllAsync(CancellationToken cancellationToken = default);
    Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
    Task<IList<TEntity>> FindAllAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

    // Counting Operations
    Task<int> CountAsync(CancellationToken cancellationToken = default);
    Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
    Task<int> CountAsync(ICountCriteriaAsync<TEntity> criteria, CancellationToken cancellationToken = default);

    // Criteria-Based Queries
    Task<IList<TEntity>> MatchAsync(ICriteriaAsync<TEntity> criteria, CancellationToken cancellationToken = default);
    Task<TEntity> MatchAsync(ICriteriaSingleAsync<TEntity> criteria, CancellationToken cancellationToken = default);

    // Foreign Entity Operations
    Task<IList<TFEntity>> MatchAsync<TFEntity>(ICriteriaForeignEntity<TEntity, TFEntity> criteria, CancellationToken cancellationToken = default) where TFEntity : class;
    Task<TFEntity> MatchAsync<TFEntity>(ICriteriaSingleForeignEntity<TEntity, TFEntity> criteria, CancellationToken cancellationToken = default) where TFEntity : class;

    // Raw SQL Operations
    Task<IList<TFEntity>> FindAllBySql<TFEntity>(string sql, CancellationToken cancellationToken, params object[] parameters);
    Task<IList<TFEntity>> FindAllBySql<TFEntity>(string sql, CancellationToken cancellationToken);
    Task<int> ExecuteSqlRaw(string sql, CancellationToken cancellationToken);
    Task<int> ExecuteSqlRaw(string sql, CancellationToken cancellationToken, params object[] parameters);

    // Tracking Operations
    void Attach(TEntity entity);
    void Detach(TEntity entity);
    void DetachAll();
}

Unit of Work Pattern

The IUnitOfWork interface coordinates operations across multiple repositories:

public interface IUnitOfWork
{
    IRepositoryAsync<TSet> GetRepositoryAsync<TSet>() where TSet : class, IBaseModel;
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
    int SaveChanges();
    void DetachAllAsync<TSet>() where TSet : class, IBaseModel;
}

Modules

Forge (Core)

The main library containing interfaces, base models, and the default repository implementations.

Key Classes and Interfaces:

  • DbContext: Abstract base class for Entity Framework DbContext with change tracking utilities
  • IRepositoryAsync<TEntity>: Generic repository interface for all entities
  • IUnitOfWork: Coordinates repository operations
  • IDbInitializer: Handles database initialization and migrations
  • BaseModel: Simple entity base class with Id
  • AuditableBaseModel: Entity base class with audit tracking
  • ForgeDbTuner: Fluent configuration builder for database options
  • ForgeDbContextPoolingOptions: Configuration for connection pooling
  • DBRepository<TEntity>: Default repository with automatic change persistence
  • DBUnitOfWork: Default unit of work implementation
  • IDataContext: Low-level database context abstraction

Forge.SqlServer

SQL Server-specific implementation with optimizations for Microsoft SQL Server.

Key Features:

  • Native SQL Server connection pooling support
  • SQL Server-specific performance tuning
  • Optimized retry policies for SQL Server transient errors

Usage:

builder.Services.AddForgeRepositorySqlServer<YourDbContext>(
    connectionString,
    poolingOptions,
    tuner => tuner.SetRetry(3)
);

Forge.PostgreSql

PostgreSQL-specific implementation with Npgsql driver support.

Key Features:

  • Npgsql-native connection pooling
  • Custom history repository for migration tracking
  • PostgreSQL-specific enum handling and optimizations

Usage:

builder.Services.AddForgeRepositoryPostgreSql<YourDbContext>(
    connectionString,
    poolingOptions,
    tuner => tuner.SetRetry(3)
);

Forge.MySql

MySQL and MariaDB implementation with MySqlConnector support.

Key Features:

  • MySqlConnector connection pooling with uint pool sizes
  • Automatic server version detection
  • MySQL-specific performance tuning

Usage:

builder.Services.AddForgeRepositoryMySql<YourDbContext>(
    connectionString,
    poolingOptions,
    tuner => tuner.SetRetry(3)
);

Forge.Oracle

Oracle database implementation with managed data access support.

Key Features:

  • Oracle connection pooling support
  • Oracle-specific command timeout handling
  • Optimized for Oracle database semantics

Usage:

builder.Services.AddForgeRepositoryOracle<YourDbContext>(
    connectionString,
    poolingOptions,
    tuner => tuner.SetRetry(3)
);

API Reference

Repository Interface Methods

Adding Entities
// Add single entity
Task AddAsync(TEntity entity, CancellationToken cancellationToken = default);

// Add multiple entities
Task AddRangeAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default);
Updating Entities
// Update single entity
Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);

// Update multiple entities
Task UpdateRangeAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default);
Removing Entities
// Remove single entity
Task RemoveAsync(TEntity entity, CancellationToken cancellationToken = default);

// Remove multiple entities
Task RemoveRangeAsync(ICollection<TEntity> entities, CancellationToken cancellationToken = default);
Querying Entities
// Get all entities
Task<IList<TEntity>> GetAllAsync(CancellationToken cancellationToken = default);

// Get entity by ID
Task<TEntity> GetByIdAsync(string id, CancellationToken cancellationToken = default);

// Find first entity matching predicate
Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

// Find all entities matching predicate
Task<IList<TEntity>> FindAllAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
Counting Entities
// Count all entities
Task<int> CountAsync(CancellationToken cancellationToken = default);

// Count entities matching predicate
Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

// Count entities matching criteria
Task<int> CountAsync(ICountCriteriaAsync<TEntity> criteria, CancellationToken cancellationToken = default);
Criteria-Based Queries
// Match multiple entities with criteria
Task<IList<TEntity>> MatchAsync(ICriteriaAsync<TEntity> criteria, CancellationToken cancellationToken = default);

// Match single entity with criteria
Task<TEntity> MatchAsync(ICriteriaSingleAsync<TEntity> criteria, CancellationToken cancellationToken = default);
Raw SQL Operations
// Execute SQL query and return mapped entities
Task<IList<TFEntity>> FindAllBySql<TFEntity>(string sql, CancellationToken cancellationToken, params object[] parameters);

// Execute raw SQL command
Task<int> ExecuteSqlRaw(string sql, CancellationToken cancellationToken, params object[] parameters);
Change Tracking
// Attach entity to context
void Attach(TEntity entity);

// Detach single entity
void Detach(TEntity entity);

// Detach all entities
void DetachAll();

Unit of Work Methods

// Get repository for entity type
IRepositoryAsync<TSet> GetRepositoryAsync<TSet>() where TSet : class, IBaseModel;

// Save all changes asynchronously
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);

// Save all changes synchronously
int SaveChanges();

// Detach all entities of specific type
void DetachAllAsync<TSet>() where TSet : class, IBaseModel;

ForgeDbTuner Configuration Methods

// Enable lazy loading proxies
ForgeDbTuner EnableLazyLoading();

// Configure warning behaviors
ForgeDbTuner ConfigureWarnings(Action<WarningsConfigurationBuilder> warningsConfigurationBuilderAction);

// Set retry count for transient failures
ForgeDbTuner SetRetry(int count);

// Set command timeout in seconds
ForgeDbTuner SetCommandTimeout(int timeoutInSeconds);

// Pool-specific tuning (database-specific)
ForgeDbTuner SetPoolingOptions(...);

Usage Examples

Basic CRUD Operations

// Adding
var product = new Product
{
    Id = Guid.NewGuid().ToString(),
    Name = "Laptop",
    Price = 999.99m,
    StockQuantity = 10
};

var repo = _unitOfWork.GetRepositoryAsync<Product>();
await repo.AddAsync(product, cancellationToken);
await _unitOfWork.SaveChangesAsync(cancellationToken);

// Retrieving
var retrieved = await repo.GetByIdAsync(product.Id, cancellationToken);

// Updating
retrieved.Price = 899.99m;
await repo.UpdateAsync(retrieved, cancellationToken);
await _unitOfWork.SaveChangesAsync(cancellationToken);

// Deleting
await repo.RemoveAsync(retrieved, cancellationToken);
await _unitOfWork.SaveChangesAsync(cancellationToken);

Querying with Predicates

var repo = _unitOfWork.GetRepositoryAsync<Product>();

// Find all expensive products
var expensiveProducts = await repo.FindAllAsync(
    p => p.Price > 1000, 
    cancellationToken
);

// Count products in stock
var inStockCount = await repo.CountAsync(
    p => p.StockQuantity > 0, 
    cancellationToken
);

// Find first product by name
var product = await repo.FindAsync(
    p => p.Name == "Laptop", 
    cancellationToken
);

Bulk Operations

var repo = _unitOfWork.GetRepositoryAsync<Product>();
var products = new List<Product> 
{
    new() { Id = "1", Name = "Product 1", Price = 10 },
    new() { Id = "2", Name = "Product 2", Price = 20 }
};

// Add multiple
await repo.AddRangeAsync(products, cancellationToken);

// Update multiple
foreach (var p in products) p.Price *= 1.1m;
await repo.UpdateRangeAsync(products, cancellationToken);

// Remove multiple
await repo.RemoveRangeAsync(products, cancellationToken);

await _unitOfWork.SaveChangesAsync(cancellationToken);

Criteria-Based Queries

public class ProductPriceCriteria : ICriteriaAsync<Product>
{
    private readonly decimal _minPrice;
    private readonly decimal _maxPrice;

    public ProductPriceCriteria(decimal minPrice, decimal maxPrice)
    {
        _minPrice = minPrice;
        _maxPrice = maxPrice;
    }

    public async Task<IList<Product>> MatchQueryFromAsync(
        IQueryable<Product> data, 
        CancellationToken cancellationToken)
    {
        return await data
            .Where(p => p.Price >= _minPrice && p.Price <= _maxPrice)
            .OrderByDescending(p => p.Price)
            .ToListAsync(cancellationToken);
    }
}

// Usage
var criteria = new ProductPriceCriteria(100, 500);
var products = await repo.MatchAsync(criteria, cancellationToken);

Raw SQL Queries

var repo = _unitOfWork.GetRepositoryAsync<Product>();

// Query with parameters
var results = await repo.FindAllBySql<Product>(
    "SELECT * FROM Products WHERE Price > @price AND StockQuantity > 0",
    cancellationToken,
    new SqlParameter("@price", 100)
);

// Execute command
var rowsAffected = await repo.ExecuteSqlRaw(
    "UPDATE Products SET Price = Price * 1.1 WHERE Category = @category",
    cancellationToken,
    new SqlParameter("@category", "Electronics")
);

Auditable Entities

public class OrderItem : AuditableBaseModel
{
    public required string OrderId { get; set; }
    public required string ProductId { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
}

// Usage with automatic audit tracking
var item = new OrderItem
{
    Id = Guid.NewGuid().ToString(),
    OrderId = orderId,
    ProductId = productId,
    Quantity = 5,
    UnitPrice = 99.99m
};

// Automatically sets CreatedOn and CreatedBy
item.OnCreate();

var repo = _unitOfWork.GetRepositoryAsync<OrderItem>();
await repo.AddAsync(item, cancellationToken);

// Later, when updating
item.Quantity = 10;
item.OnUpdate();
await repo.UpdateAsync(item, cancellationToken);

// For soft delete
item.OnDelete();
await repo.UpdateAsync(item, cancellationToken);

Connection Pooling Configuration

var poolingOptions = new ForgeDbContextPoolingOptions
{
    EnablePooling = true,
    MinPoolSize = 5,
    MaxPoolSize = 50
};

builder.Services.AddForgeRepositorySqlServer<AppDbContext>(
    connectionString,
    poolingOptions,
    tuner => tuner
        .SetRetry(3)
        .SetCommandTimeout(30)
        .EnableLazyLoading()
);

Transactional Operations

public async Task TransferProductAsync(string fromOrderId, string toOrderId, CancellationToken cancellationToken)
{
    try
    {
        var itemRepo = _unitOfWork.GetRepositoryAsync<OrderItem>();

        var items = await itemRepo.FindAllAsync(
            i => i.OrderId == fromOrderId, 
            cancellationToken
        );

        foreach (var item in items)
        {
            item.OrderId = toOrderId;
        }

        await itemRepo.UpdateRangeAsync(items, cancellationToken);

        // All changes committed as single transaction
        await _unitOfWork.SaveChangesAsync(cancellationToken);
    }
    catch (Exception ex)
    {
        // Changes automatically rolled back on exception
        throw;
    }
}

Contributing

Contributions are welcome! Please submit issues to help improve Forge.Repository.

License

This project is licensed under the LICENSE file in the repository.


Author: Sayem
Website: https://www.sayem.xyz/packages/forge-repository
Version: 10.0.1
Target Framework: .NET 10

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.1 36 5/27/2026
10.0.0 52 5/25/2026
1.0.0-alpha.14 64 4/13/2026
1.0.0-alpha.13 51 4/13/2026
1.0.0-alpha.12 62 4/5/2026