Maurosoft.Net.RepositoryPattern 1.0.6

There is a newer version of this package available.
See the version list below for details.
dotnet add package Maurosoft.Net.RepositoryPattern --version 1.0.6
                    
NuGet\Install-Package Maurosoft.Net.RepositoryPattern -Version 1.0.6
                    
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="Maurosoft.Net.RepositoryPattern" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Maurosoft.Net.RepositoryPattern" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="Maurosoft.Net.RepositoryPattern" />
                    
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 Maurosoft.Net.RepositoryPattern --version 1.0.6
                    
#r "nuget: Maurosoft.Net.RepositoryPattern, 1.0.6"
                    
#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 Maurosoft.Net.RepositoryPattern@1.0.6
                    
#: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=Maurosoft.Net.RepositoryPattern&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=Maurosoft.Net.RepositoryPattern&version=1.0.6
                    
Install as a Cake Tool

Maurosoft Repository Pattern

Una libreria per .NET 9 che fornisce un’implementazione pulita ed estensibile del Repository Pattern per l’accesso a più database.
Aggiunge un livello di astrazione utilizzando RepoDB.Net e Dapper, offrendo un approccio unificato per interagire con SQL Server, MySQL e ClickHouse.
(Il supporto a PostgreSQL è attualmente in sviluppo 🚧)


✨ Funzionalità

  • 🔗 Implementazione unificata del Repository Pattern
  • ⚡ Registrazione semplificata repository tramite classe base
  • 🛠 Supporto per più ORM: RepoDB.Net e Dapper
  • 🗄 Compatibile con:
    • Microsoft SQL Server
    • MySQL
    • ClickHouse
    • PostgreSQL (in arrivo)
  • ⚡ Ottimizzata per .NET 9
  • ♻️ Supporto a transazioni con unit of work
  • 🧩 Estendibile facilmente per nuovi provider

📦 Installazione

Aggiungi il pacchetto tramite NuGet:

dotnet add package Maurosoft.Net.RepositoryPattern

⚙️ Configurazione

La libreria utilizza un approccio multi–database configurabile tramite appsettings.json.

È possibile definire uno o più endpoint, ciascuno con il relativo provider, connection string e l’eventuale abilitazione del supporto alle Unit of Work.

Esempio di configurazione:

{
  "Database": {
    "Default": "PrimarySql",
    "Endpoints": {
      "PrimarySql": {
        "Provider": "SqlServer",
        "UnitOfWork": true,
        "ConnectionString": "Data Source=server1;Initial Catalog=app;User Id=sa;Password=Pass@word1!;TrustServerCertificate=True;MultipleActiveResultSets=True;Application Name=Repository Pattern Library"
      },
      "SecondarySql": {
        "Provider": "SqlServer",
        "UnitOfWork": false,
        "ConnectionString": "Data Source=server2;Initial Catalog=app;User Id=sa;Password=Pass@word1!;TrustServerCertificate=True;MultipleActiveResultSets=True;Application Name=Repository Pattern Library"
      },
      "MySqlMain": {
        "Provider": "MySql",
        "UnitOfWork": true,
        "ConnectionString": "Server=server3;Port=3306;Database=app;User Id=root;Password=pass;"
      }
      "ClickHouseDW": {
        "Provider": "ClickHouse",
        "ConnectionString": "Host=server4;Port=8123;Database=dw;Username=default;Password="
      }
    }
  }
}

🧩 IRepository<TEntity> Metodi — DB Support Draft

Legenda: ✅ Supported · ⚠️ Limited/Workaround · ❌ Not available / impractical

Nome metodo Descrizione SqlServer MySql PostgreSQL ClickHouse
Attach(IUnitOfWork unitOfWork) Attaches this repository to a unit of work to share the same database transaction.
EndPoint Gets the logical connection name used to resolve the IDataContext<TConnection>.
Fields Gets the list of fields used in queries.
Average(Expression<Func<TEntity, object>> field, Expression<Func<TEntity, bool>>? where = null) Calculates the average of the values of the specified field that satisfy an optional filter condition.
AverageAsync(Expression<Func<TEntity, object>> field, Expression<Func<TEntity, bool>>? where = null) Calculates the average of the values of the specified field that satisfy an optional filter condition.
BulkDelete(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>>? qualifiers = null, int bulkCopyTimeout = 300, int batchSize = 10000) Performs a bulk delete on a collection of entities.
BulkInsert(string tableName, IEnumerable<TEntity> entities, IEnumerable<DatabaseBulkInsertMapItem>? mappings = null, int bulkCopyTimeout = 300, int batchSize = 10000) Performs a bulk insert into the specified table.
BulkInsert<T>(string tableName, IEnumerable<T> entities, Action<T, int, DataRow, DataTable> itemToRow, IDbTransaction? transaction, int? batchSize = null) Performs a bulk insert using a custom mapper from item to DataRow.
BulkMerge(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>>? qualifiers = null, int bulkCopyTimeout = 300, int batchSize = 10000) Performs a bulk merge (upsert) into a specific table for the current TEntity.
BulkMerge(string tableName, IEnumerable<TEntity> entities, Expression<Func<TEntity, object>>? qualifiers = null, int bulkCopyTimeout = 300, int batchSize = 10000) Performs a bulk merge (upsert) into a specific table for the current TEntity.
BulkMerge(string tableSource, string tableDestination, Expression<Func<TEntity, object>>? qualifiers = null, int bulkCopyTimeout = 300, int batchSize = 10000) Loads all rows from a source table into memory and performs a bulk merge into the destination table.
CopyFrom(string endPointSource, string commandText, object? param = null, CommandType? commandType = null, int commandTimeout = 60, IEnumerable<DatabaseField>? qualifiers = null) Copies data from a specified source endpoint into the current repository endpoint by executing a query on the source and performing a bulk merge (upsert) into the current endpoint.
Count(Expression<Func<TEntity, bool>>? where = null) Returns the number of entities that satisfy an optional filter condition.
CountAsync(Expression<Func<TEntity, bool>>? where = null) Returns the number of entities that satisfy an optional filter condition.
CreateTable(bool temporary = true, string name = "temp", string fields = "", bool dropIfExists = true, bool randomName = true) Creates a temporary or permanent table based on the provided options.
Delete(object id) Deletes an entity by primary key.
DropTable(bool temporary = true, string name = "temp") Drops a temporary or permanent table.
ExecuteNonQuery(string commandText, object? param = null, CommandType? commandType = null, int commandTimeout = 60) Executes a non-query SQL command (e.g., INSERT, UPDATE, DELETE).
GetAll(bool cache = false, bool invalidateCache = false, string cacheKey = "GetAll", TimeSpan? cacheDuration = null) Retrieves all entities, optionally leveraging a cache mechanism.
Insert(TEntity entity, Func<TEntity, bool>? action = null) Inserts a single entity and optionally executes a post-insert action.
InsertAll(IEnumerable<TEntity> entities) Inserts multiple entities in a set-based operation.
Max(Expression<Func<TEntity, object>> field, Expression<Func<TEntity, bool>>? where = null) Calculates the maximum of the values of the specified field that satisfy an optional filter condition.
MaxAsync(Expression<Func<TEntity, object>> field, Expression<Func<TEntity, bool>>? where = null) Calculates the maximum of the values of the specified field that satisfy an optional filter condition.
Merge(TEntity entity, IEnumerable<DatabaseField>? qualifiers = null) Merges (upserts) a single entity using optional qualifiers.
MergeAll(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> qualifiers) Merges (upserts) a sequence of entities using a lambda-based qualifier.
MergeAll(IEnumerable<TEntity> entities, IEnumerable<DatabaseField> qualifiers) Merges (upserts) a sequence of entities using an explicit list of qualifier fields.
MergeAll(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> qualifiers, IEnumerable<DatabaseField> fields) Merges (upserts) a sequence of entities specifying both qualifiers and an explicit field list.
Min(Expression<Func<TEntity, object>> field, Expression<Func<TEntity, bool>>? where = null) Calculates the minimun of the values of the specified field that satisfy an optional filter condition.
MinAsync(Expression<Func<TEntity, object>> field, Expression<Func<TEntity, bool>>? where = null) Calculates the minimun of the values of the specified field that satisfy an optional filter condition.
Query(string commandText, object? param = null, CommandType? commandType = null, int commandTimeout = 60) Executes an ad-hoc SQL query and returns the results projected to TEntity.
Query(Expression<Func<TEntity, bool>> where, bool cache = false, bool invalidateCache = false, string cacheKey = "Query", TimeSpan? cacheDuration = null) Queries entities using a LINQ where-clause and optional caching.
QuerySingle(string commandText, object? param = null, CommandType? commandType = null, int commandTimeout = 60) Retrieves a single entity by predicate, applying ordering and an optional in-place update before returning it.
QuerySingle(Expression<Func<TEntity, bool>> where, bool cache = false, bool invalidateCache = false, string cacheKey = "QuerySingle", TimeSpan? cacheDuration = null) Retrieves a single entity by predicate, applying ordering and an optional in-place update before returning it.
QuerySingleWithUpdate<TEntityOut>(Expression<Func<TEntity, bool>> where, DatabaseSortDirection sortDirection, Func<TEntity, TEntityOut> orderByCriteria, Func<TEntity, TEntity>? funcUpdate) Retrieves a single entity by predicate, applying ordering and an optional in-place update before returning it.
Update(TEntity? entity, IEnumerable<DatabaseField>? fields = null) Updates a single entity instance.
Update(Expression<Func<TEntity, bool>> where, Func<TEntity, TEntity> fields) Updates the entities that matches the predicate by applying a field-transform function.

🚀 Utilizzo

Un caso di utilizzo per copiare i dati di una tabella da 2 database diversi (MySql e SqlServer)

using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Maurosoft.Net.RepositoryPattern.Interfaces;
using Maurosoft.Net.RepositoryPattern.Model;
using System.Data;
using Maurosoft.Net.RepositoryPattern;
using ZiggyCreatures.Caching.Fusion;

var host = Host.CreateDefaultBuilder(args)
    .ConfigureAppConfiguration(cfg =>
    {
        cfg.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
        cfg.AddEnvironmentVariables();
    })
    .ConfigureServices((ctx, services) =>
    {
        services.AddRepositoryPattern(ctx.Configuration);
        services.AddKeyedScoped<IRepository<User>>("UserRepositoryMySql", (c, _) => new RepositoryPattern.Services.Repository<User>(c.GetRequiredService<IDbConnectionFactory>(), c.GetRequiredService<IFusionCache>(), "MySql"));
        services.AddKeyedScoped<IRepository<User>>("UserRepositorySqlServer", (c, _) => new RepositoryPattern.Services.Repository<User>(c.GetRequiredService<IDbConnectionFactory>(), c.GetRequiredService<IFusionCache>(), "SqlServer"));
    })
    .Build();

/*
- Sorgente: legge da MySql usando la SELECT (parametrizzata).
- Destinazione: il repository è attaccato a SqlServer → scrive su SQL Server.
- DatabaseField("UserName") definisce la/e colonne chiave di corrispondenza per il merge:
  - se UserName esiste già nel target → UPDATE della riga,
  - altrimenti → INSERT.
- Ritorno: rowAffected = numero di righe inserite/aggiornate nel target.
*/
using (var scoped = host.Services.CreateScope())
{
    var repo = scoped.ServiceProvider.GetRequiredKeyedService<IRepository<User>>("UserRepositorySqlServer");
    var uow = scoped.ServiceProvider.GetRequiredKeyedService<IUnitOfWork>("UnitOfWorkSqlServer");

    try
    {
      repo.Attach(uow);
      uow.Begin();

      // Merge degli utenti ... utilizzando il campo Username come chiave.
      var rowAffected = repo.CopyFrom(
          "MySql",                                       // endpoint sorgente (MySQL)
          "SELECT * FROM Users Where UserId > @UserId",  // query sorgente
          new { UserId = 1 },                            // parametri query
          CommandType.Text,                              // tipo comando
          60,                                            // timeout esecuzione (sec.)
          [ new DatabaseField("UserName") ]              // chiavi di merge (se non specificata, viene utilizzata la chiave primaria)
      );

      uow.Commit();
      
      Console.WriteLine($"Rows Affected: {rowAffected}");
    }
    catch
    {
        uow.Rollback();
        throw;
    }
}

[Table("Users")]
public class User
{
    public int UserId { get; set; }
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string UserName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
}

🛡 Requisiti

  • .NET 9
  • Uno o più database supportati in esecuzione

📌 Roadmap

  • Supporto SQL Server
  • Supporto MySQL
  • Supporto ClickHouse
  • Supporto PostgreSQL
  • Integrazione avanzata con caching
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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
1.0.7 197 10/15/2025
1.0.6 173 10/12/2025
1.0.5 169 10/12/2025
1.0.4 177 10/12/2025
1.0.2 133 10/11/2025