PostgreSQL integration for NuvTools.Data.EntityFrameworkCore with simplified DbContext registration, configuration from appsettings.json, and snake_case naming convention support.
$ dotnet add package NuvTools.Data.EntityFrameworkCore.PostgreSQLNuv Tools Data Libraries are a set of .NET libraries designed to simplify and standardize data access and manipulation. They provide abstractions and helpers for common data operations, as well as seamless integration with Entity Framework Core for SQL Server and PostgreSQL.
IResult or IResult<T> for consistent error handlingCancellationToken supportCore library with generic helpers for data manipulation:
IQueryable and IEnumerable collectionsdotnet add package NuvTools.DataExtensions for Entity Framework Core:
SyncFromListAsync, AddOrUpdateFromListAsync, AddOrRemoveFromListAsyncPagingWrapAsync for efficient database pagingdotnet add package NuvTools.Data.EntityFrameworkCoreSpecialized helpers for SQL Server with EF Core:
AddDatabase and AddDatabaseByConnectionName extension methodsappsettings.jsonSqlServerDbContextOptionsBuilderdotnet add package NuvTools.Data.EntityFrameworkCore.SqlServerSpecialized helpers for PostgreSQL with EF Core:
AddDatabase and AddDatabaseByConnectionName extension methodsUseSnakeCaseNamingConvention for PostgreSQL naming standardsNpgsqlDbContextOptionsBuilderdotnet add package NuvTools.Data.EntityFrameworkCore.PostgreSQLusing NuvTools.Data.Paging;
// In-memory paging (0-indexed)
var items = new List<Product> { /* ... */ };
var pagedResult = items.PagingWrap(pageIndex: 0, pageSize: 20);
Console.WriteLine($"Page {pagedResult.PageIndex + 1} of {Math.Ceiling(pagedResult.Total / 20.0)}");
foreach (var item in pagedResult.List)
{
Console.WriteLine(item.Name);
}using NuvTools.Data.Sorting;
using NuvTools.Data.Sorting.Enumerations;
var sortedProducts = products
.Sort(p => p.Category, SortDirection.ASC)
.ThenSort(p => p.Price, SortDirection.DESC);using NuvTools.Data.EntityFrameworkCore.SqlServer.Extensions;
// In Program.cs or Startup.cs
builder.Services.AddDatabaseByConnectionName<MyDbContext>("DefaultConnection");
// Or with connection string directly
builder.Services.AddDatabase<MyDbContext>(connectionString);
// With SQL Server-specific options
builder.Services.AddDatabaseByConnectionName<MyDbContext>(
"DefaultConnection",
sqlServerOptions => sqlServerOptions.EnableRetryOnFailure()
);using NuvTools.Data.EntityFrameworkCore.PostgreSQL.Extensions;
// Register DbContext
builder.Services.AddDatabaseByConnectionName<MyDbContext>("PostgresConnection");
// In your DbContext
public class MyDbContext : DbContextBase
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Apply snake_case naming convention for PostgreSQL
modelBuilder.UseSnakeCaseNamingConvention();
base.OnModelCreating(modelBuilder);
}
}using NuvTools.Data.EntityFrameworkCore.Context;
public class MyDbContext : DbContextBase
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
}
// In your service
public class ProductService
{
private readonly MyDbContext _context;
public async Task<IResult<int>> CreateProductAsync(Product product)
{
// AddAndSaveAsync returns IResult<TKey>
return await _context.AddAndSaveAsync<Product, int>(product);
}
public async Task<IResult> UpdateProductAsync(Product product, int id)
{
// UpdateAndSaveAsync returns IResult
return await _context.UpdateAndSaveAsync(product, id);
}
public async Task<IResult> DeleteProductAsync(int id)
{
// RemoveAndSaveAsync returns IResult
return await _context.RemoveAndSaveAsync<Product>(id);
}
}using NuvTools.Data.EntityFrameworkCore.Paging;
public async Task<PagingWithEnumerableList<Product>> GetProductsAsync(int pageIndex, int pageSize)
{
var query = _context.Products.Where(p => p.IsActive);
// PagingWrapAsync materializes the data (0-indexed)
var pagedResult = await query.PagingWrapWithEnumerableListAsync(pageIndex, pageSize);
return pagedResult;
}// Sync from list: Add new, update existing, remove missing
var result = await _context.SyncFromListAsync(
updatedProducts,
p => p.Id,
p => p.IsActive // Optional filter
);
// Add or update only (no removal)
await _context.AddOrUpdateFromListAsync(products, p => p.Id);
// Add or remove only (no updates)
await _context.AddOrRemoveFromListAsync(products, p => p.Id);dotnet build NuvTools.Data.slnx# Run all tests
dotnet test
# Run specific test project
dotnet test tests/NuvTools.Data.Test/NuvTools.Data.Test.csprojdotnet build NuvTools.Data.slnx -c ReleasePackages are automatically generated in bin/Release folders when building in Release configuration.
PageNumber to 0-based PageIndexPageNumber renamed to PageIndex in PagingBase, PagingFilter, and paging resultsGetPageNumber() renamed to GetPageIndex() in PagingHelper1 to 0This project is licensed under the terms specified in the LICENSE file.
Contributions are welcome! Please feel free to submit a Pull Request.