VOOZH about

URL: https://www.nuget.org/packages/DKNet.EfCore.Repos.Abstractions/

⇱ NuGet Gallery | DKNet.EfCore.Repos.Abstractions 9.5.39




👁 Image
DKNet.EfCore.Repos.Abstractions 9.5.39

dotnet add package DKNet.EfCore.Repos.Abstractions --version 9.5.39
 
 
NuGet\Install-Package DKNet.EfCore.Repos.Abstractions -Version 9.5.39
 
 
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="DKNet.EfCore.Repos.Abstractions" Version="9.5.39" />
 
 
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DKNet.EfCore.Repos.Abstractions" Version="9.5.39" />
 
Directory.Packages.props
<PackageReference Include="DKNet.EfCore.Repos.Abstractions" />
 
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 DKNet.EfCore.Repos.Abstractions --version 9.5.39
 
 
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: DKNet.EfCore.Repos.Abstractions, 9.5.39"
 
 
#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 DKNet.EfCore.Repos.Abstractions@9.5.39
 
 
#: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=DKNet.EfCore.Repos.Abstractions&version=9.5.39
 
Install as a Cake Addin
#tool nuget:?package=DKNet.EfCore.Repos.Abstractions&version=9.5.39
 
Install as a Cake Tool
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

DKNet.EfCore.Repos.Abstractions

👁 NuGet
👁 NuGet Downloads
👁 .NET

Repository pattern abstractions for Entity Framework Core, providing clean separation between read and write operations with strongly-typed interfaces. This package defines the contracts for data access operations following CQRS principles and Domain-Driven Design patterns.

Features

  • Repository Pattern Abstractions: Clean interfaces for data access operations
  • CQRS Support: Separate read and write operations with dedicated interfaces
  • Generic Entity Support: Type-safe operations for any entity type
  • Async/Await Operations: Full async support with cancellation tokens
  • Transaction Management: Built-in transaction support for write operations
  • Projection Support: Efficient DTO projections for read operations
  • Query Flexibility: IQueryable support for complex queries
  • Batch Operations: Support for bulk add, update, and delete operations

Supported Frameworks

  • .NET 9.0+
  • Entity Framework Core 9.0+

Installation

Install via NuGet Package Manager:

dotnet add package DKNet.EfCore.Repos.Abstractions

Or via Package Manager Console:

Install-Package DKNet.EfCore.Repos.Abstractions

Quick Start

Basic Repository Interface Usage

using DKNet.EfCore.Repos.Abstractions;

// Domain entity
public class Product : Entity<Guid>
{
 public string Name { get; set; }
 public decimal Price { get; set; }
 public string Category { get; set; }
}

// Custom repository interface
public interface IProductRepository : IRepository<Product>
{
 Task<IEnumerable<Product>> GetProductsByCategoryAsync(string category, CancellationToken cancellationToken = default);
 Task<bool> ExistsByNameAsync(string name, CancellationToken cancellationToken = default);
}

// Service using repository
public class ProductService
{
 private readonly IProductRepository _productRepository;

 public ProductService(IProductRepository productRepository)
 {
 _productRepository = productRepository;
 }

 public async Task<Product> CreateProductAsync(string name, decimal price, string category)
 {
 // Check if product already exists
 if (await _productRepository.ExistsByNameAsync(name))
 throw new InvalidOperationException($"Product with name '{name}' already exists");

 var product = new Product 
 { 
 Name = name, 
 Price = price, 
 Category = category 
 };

 await _productRepository.AddAsync(product);
 await _productRepository.SaveChangesAsync();

 return product;
 }
}

Read-Only Operations

public class ProductQueryService
{
 private readonly IReadRepository<Product> _readRepository;

 public ProductQueryService(IReadRepository<Product> readRepository)
 {
 _readRepository = readRepository;
 }

 public async Task<List<ProductDto>> GetActiveProductsAsync()
 {
 // Use projection for efficient queries
 return await _readRepository
 .GetDto<ProductDto>(p => p.IsActive)
 .OrderBy(p => p.Name)
 .ToListAsync();
 }

 public async Task<Product?> GetProductByIdAsync(Guid id)
 {
 return await _readRepository.FindAsync(id);
 }

 public IQueryable<Product> GetProductsQuery()
 {
 // Return IQueryable for complex filtering
 return _readRepository.Gets();
 }
}

public class ProductDto
{
 public Guid Id { get; set; }
 public string Name { get; set; }
 public decimal Price { get; set; }
 public string Category { get; set; }
}

Write Operations with Transactions

public class ProductManagementService
{
 private readonly IWriteRepository<Product> _writeRepository;

 public ProductManagementService(IWriteRepository<Product> writeRepository)
 {
 _writeRepository = writeRepository;
 }

 public async Task BulkUpdatePricesAsync(List<ProductPriceUpdate> updates)
 {
 using var transaction = await _writeRepository.BeginTransactionAsync();

 try
 {
 foreach (var update in updates)
 {
 var product = await _writeRepository.FindAsync(update.ProductId);
 if (product != null)
 {
 product.Price = update.NewPrice;
 await _writeRepository.UpdateAsync(product);
 }
 }

 await _writeRepository.SaveChangesAsync();
 await transaction.CommitAsync();
 }
 catch
 {
 await transaction.RollbackAsync();
 throw;
 }
 }

 public async Task AddProductsInBatchAsync(List<Product> products)
 {
 await _writeRepository.AddRangeAsync(products);
 await _writeRepository.SaveChangesAsync();
 }
}

public class ProductPriceUpdate
{
 public Guid ProductId { get; set; }
 public decimal NewPrice { get; set; }
}

Configuration

Repository Registration Pattern

using Microsoft.Extensions.DependencyInjection;
using DKNet.EfCore.Repos.Abstractions;

// Register repositories in DI container
public static class ServiceCollectionExtensions
{
 public static IServiceCollection AddRepositories(this IServiceCollection services)
 {
 // Register read-only repositories
 services.AddScoped<IReadRepository<Product>, ProductReadRepository>();
 services.AddScoped<IReadRepository<Customer>, CustomerReadRepository>();

 // Register write repositories
 services.AddScoped<IWriteRepository<Product>, ProductWriteRepository>();
 services.AddScoped<IWriteRepository<Customer>, CustomerWriteRepository>();

 // Register full repositories
 services.AddScoped<IRepository<Product>, ProductRepository>();
 services.AddScoped<IRepository<Customer>, CustomerRepository>();

 // Register custom repositories
 services.AddScoped<IProductRepository, ProductRepository>();
 services.AddScoped<ICustomerRepository, CustomerRepository>();

 return services;
 }
}

API Reference

Core Interfaces

  • IRepository<TEntity> - Combined read and write operations
  • IReadRepository<TEntity> - Read-only operations and queries
  • IWriteRepository<TEntity> - Write operations and transaction management

Read Operations

  • Gets() - Get IQueryable for entity
  • GetDto<TModel>(Expression<Func<TEntity, bool>>?) - Get projection with optional filter
  • FindAsync(object, CancellationToken) - Find entity by primary key
  • FindAsync(object[], CancellationToken) - Find entity by composite key
  • AnyAsync(Expression<Func<TEntity, bool>>, CancellationToken) - Check if any entity matches condition
  • CountAsync(Expression<Func<TEntity, bool>>, CancellationToken) - Count entities matching condition

Write Operations

  • AddAsync(TEntity, CancellationToken) - Add single entity
  • AddRangeAsync(IEnumerable<TEntity>, CancellationToken) - Add multiple entities
  • UpdateAsync(TEntity, CancellationToken) - Update single entity
  • UpdateRangeAsync(IEnumerable<TEntity>, CancellationToken) - Update multiple entities
  • DeleteAsync(TEntity, CancellationToken) - Delete single entity
  • DeleteRangeAsync(IEnumerable<TEntity>, CancellationToken) - Delete multiple entities
  • SaveChangesAsync(CancellationToken) - Persist changes to database

Transaction Management

  • BeginTransactionAsync(CancellationToken) - Begin database transaction
  • Entry(TEntity) - Get EntityEntry for change tracking

Advanced Usage

Custom Repository with Business Logic

public interface IOrderRepository : IRepository<Order>
{
 Task<IEnumerable<Order>> GetOrdersByStatusAsync(OrderStatus status, CancellationToken cancellationToken = default);
 Task<Order?> GetOrderWithItemsAsync(Guid orderId, CancellationToken cancellationToken = default);
 Task<decimal> GetTotalSalesAsync(DateTime fromDate, DateTime toDate, CancellationToken cancellationToken = default);
}

public class OrderService
{
 private readonly IOrderRepository _orderRepository;
 private readonly IProductRepository _productRepository;

 public OrderService(IOrderRepository orderRepository, IProductRepository productRepository)
 {
 _orderRepository = orderRepository;
 _productRepository = productRepository;
 }

 public async Task<Order> CreateOrderAsync(Guid customerId, List<OrderItemRequest> items)
 {
 using var transaction = await _orderRepository.BeginTransactionAsync();

 try
 {
 var order = new Order(customerId);

 // Validate and add items
 foreach (var item in items)
 {
 var product = await _productRepository.FindAsync(item.ProductId);
 if (product == null)
 throw new InvalidOperationException($"Product {item.ProductId} not found");

 order.AddItem(item.ProductId, item.Quantity, product.Price);
 }

 await _orderRepository.AddAsync(order);
 await _orderRepository.SaveChangesAsync();
 await transaction.CommitAsync();

 return order;
 }
 catch
 {
 await transaction.RollbackAsync();
 throw;
 }
 }
}

Repository with Specifications Pattern

public class ProductSpecificationService
{
 private readonly IReadRepository<Product> _readRepository;

 public ProductSpecificationService(IReadRepository<Product> readRepository)
 {
 _readRepository = readRepository;
 }

 public async Task<List<Product>> GetProductsAsync(ProductSearchCriteria criteria)
 {
 var query = _readRepository.Gets();

 if (!string.IsNullOrEmpty(criteria.Category))
 query = query.Where(p => p.Category == criteria.Category);

 if (criteria.MinPrice.HasValue)
 query = query.Where(p => p.Price >= criteria.MinPrice.Value);

 if (criteria.MaxPrice.HasValue)
 query = query.Where(p => p.Price <= criteria.MaxPrice.Value);

 if (!string.IsNullOrEmpty(criteria.SearchTerm))
 query = query.Where(p => p.Name.Contains(criteria.SearchTerm));

 return await query
 .OrderBy(p => p.Name)
 .Skip(criteria.Skip)
 .Take(criteria.Take)
 .ToListAsync();
 }
}

public class ProductSearchCriteria
{
 public string? Category { get; set; }
 public decimal? MinPrice { get; set; }
 public decimal? MaxPrice { get; set; }
 public string? SearchTerm { get; set; }
 public int Skip { get; set; } = 0;
 public int Take { get; set; } = 50;
}

Unit of Work Pattern Integration

public interface IUnitOfWork
{
 IProductRepository Products { get; }
 ICustomerRepository Customers { get; }
 IOrderRepository Orders { get; }
 
 Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
 Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
}

public class BusinessService
{
 private readonly IUnitOfWork _unitOfWork;

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

 public async Task ProcessOrderAsync(OrderRequest request)
 {
 using var transaction = await _unitOfWork.BeginTransactionAsync();

 try
 {
 // Create customer if not exists
 var customer = await _unitOfWork.Customers.FindAsync(request.CustomerId);
 if (customer == null)
 {
 customer = new Customer(request.CustomerEmail);
 await _unitOfWork.Customers.AddAsync(customer);
 }

 // Create order
 var order = new Order(customer.Id);
 await _unitOfWork.Orders.AddAsync(order);

 // Update product inventory
 foreach (var item in request.Items)
 {
 var product = await _unitOfWork.Products.FindAsync(item.ProductId);
 if (product != null)
 {
 product.ReduceInventory(item.Quantity);
 await _unitOfWork.Products.UpdateAsync(product);
 }
 }

 await _unitOfWork.SaveChangesAsync();
 await transaction.CommitAsync();
 }
 catch
 {
 await transaction.RollbackAsync();
 throw;
 }
 }
}

Design Principles

CQRS Separation

  • IReadRepository: Optimized for queries and projections
  • IWriteRepository: Focused on data modifications and transactions
  • IRepository: Combines both when full access is needed

Entity Framework Integration

  • Direct integration with EF Core change tracking
  • Transaction support through IDbContextTransaction
  • IQueryable support for deferred execution

Testability

  • Interface-based design for easy mocking
  • Separation of concerns between read and write operations
  • Clear contracts for business logic testing

Performance Considerations

  • Projections: Use GetDto<T>() for efficient queries that only select needed columns
  • IQueryable: Leverage deferred execution for complex query building
  • Batch Operations: Use range methods for bulk operations
  • Transactions: Use transactions for atomic operations across multiple entities
  • Change Tracking: EF Core change tracking is automatically managed

Thread Safety

  • Repository instances should be scoped to request/operation lifetime
  • Concurrent access to different entities is safe
  • Shared entity instances require external synchronization
  • Transaction isolation follows EF Core/database provider rules

Contributing

See the main for guidelines on how to contribute to this project.

License

This project is licensed under the .

Related Packages

  • - Concrete repository implementations
  • - Core entity abstractions
  • - EF Core functionality extensions
  • - Specification pattern support

Part of the DKNet Framework - A comprehensive .NET framework for building modern, scalable applications.

Product Versions Compatible and additional computed target framework versions.
.NET net9.0 net9.0 is compatible.  net9.0-android net9.0-android was computed.  net9.0-browser net9.0-browser was computed.  net9.0-ios net9.0-ios was computed.  net9.0-maccatalyst net9.0-maccatalyst was computed.  net9.0-macos net9.0-macos was computed.  net9.0-tvos net9.0-tvos was computed.  net9.0-windows net9.0-windows was computed.  net10.0 net10.0 was computed.  net10.0-android net10.0-android was computed.  net10.0-browser net10.0-browser was computed.  net10.0-ios net10.0-ios was computed.  net10.0-maccatalyst net10.0-maccatalyst was computed.  net10.0-macos net10.0-macos was computed.  net10.0-tvos net10.0-tvos was computed.  net10.0-windows 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 (1)

Showing the top 1 NuGet packages that depend on DKNet.EfCore.Repos.Abstractions:

Package Downloads
DKNet.EfCore.Repos

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
9.5.39 463 11/13/2025
9.5.38 291 11/6/2025
9.5.37 269 11/5/2025
9.5.36 279 11/5/2025
9.5.35 266 11/4/2025
9.5.34 264 11/4/2025
9.5.33 268 11/3/2025
9.5.32 258 11/3/2025
9.5.31 246 10/31/2025
9.5.30 257 10/31/2025
9.5.29 278 10/30/2025
9.5.28 257 10/27/2025
9.5.27 276 10/27/2025
9.5.26 253 10/27/2025
9.5.25 237 10/26/2025
9.5.24 197 10/25/2025
9.5.23 189 10/25/2025
9.5.22 188 10/25/2025
9.5.21 262 10/24/2025
9.5.20 273 10/23/2025
Loading failed