![]() |
VOOZH | about |
dotnet add package DKNet.EfCore.Repos --version 9.5.39
NuGet\Install-Package DKNet.EfCore.Repos -Version 9.5.39
<PackageReference Include="DKNet.EfCore.Repos" Version="9.5.39" />
<PackageVersion Include="DKNet.EfCore.Repos" Version="9.5.39" />Directory.Packages.props
<PackageReference Include="DKNet.EfCore.Repos" />Project file
paket add DKNet.EfCore.Repos --version 9.5.39
#r "nuget: DKNet.EfCore.Repos, 9.5.39"
#:package DKNet.EfCore.Repos@9.5.39
#addin nuget:?package=DKNet.EfCore.Repos&version=9.5.39Install as a Cake Addin
#tool nuget:?package=DKNet.EfCore.Repos&version=9.5.39Install as a Cake Tool
👁 NuGet
👁 NuGet Downloads
👁 .NET
Concrete implementations of the Repository pattern for Entity Framework Core, providing ready-to-use repository classes that implement the abstractions from DKNet.EfCore.Repos.Abstractions. This package includes generic repositories, automatic DI registration, and Mapster integration for projections.
Install via NuGet Package Manager:
dotnet add package DKNet.EfCore.Repos
Or via Package Manager Console:
Install-Package DKNet.EfCore.Repos
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Order> Orders { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}
// Configure services
public void ConfigureServices(IServiceCollection services)
{
// Add DbContext
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString));
// Add Mapster for projections
services.AddMapster();
// Add generic repositories
services.AddGenericRepositories<AppDbContext>();
}
public class ProductService
{
private readonly IRepository<Product> _productRepository;
private readonly IReadRepository<Customer> _customerRepository;
public ProductService(
IRepository<Product> productRepository,
IReadRepository<Customer> customerRepository)
{
_productRepository = productRepository;
_customerRepository = customerRepository;
}
public async Task<Product> CreateProductAsync(CreateProductRequest request)
{
var product = new Product(request.Name, request.Price, request.Category);
await _productRepository.AddAsync(product);
await _productRepository.SaveChangesAsync();
return product;
}
public async Task<List<ProductDto>> GetActiveProductsAsync()
{
// Efficient projection using Mapster
return await _productRepository
.GetDto<ProductDto>(p => p.IsActive)
.OrderBy(p => p.Name)
.ToListAsync();
}
public async Task<Product?> GetProductByIdAsync(Guid id)
{
return await _productRepository.FindAsync(id);
}
}
public class ProductDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
public class OrderQueryService
{
private readonly IReadRepository<Order> _orderReadRepository;
public OrderQueryService(IReadRepository<Order> orderReadRepository)
{
_orderReadRepository = orderReadRepository;
}
public async Task<OrderSummaryDto?> GetOrderSummaryAsync(Guid orderId)
{
return await _orderReadRepository
.GetDto<OrderSummaryDto>(o => o.Id == orderId)
.FirstOrDefaultAsync();
}
public async Task<List<OrderListDto>> GetCustomerOrdersAsync(Guid customerId)
{
return await _orderReadRepository
.GetDto<OrderListDto>(o => o.CustomerId == customerId)
.OrderByDescending(o => o.CreatedDate)
.ToListAsync();
}
}
public class OrderCommandService
{
private readonly IWriteRepository<Order> _orderWriteRepository;
private readonly IReadRepository<Product> _productReadRepository;
public OrderCommandService(
IWriteRepository<Order> orderWriteRepository,
IReadRepository<Product> productReadRepository)
{
_orderWriteRepository = orderWriteRepository;
_productReadRepository = productReadRepository;
}
public async Task<Guid> CreateOrderAsync(CreateOrderRequest request)
{
using var transaction = await _orderWriteRepository.BeginTransactionAsync();
try
{
var order = new Order(request.CustomerId);
// Validate products exist
foreach (var item in request.Items)
{
var product = await _productReadRepository.FindAsync(item.ProductId);
if (product == null)
throw new InvalidOperationException($"Product {item.ProductId} not found");
order.AddItem(item.ProductId, item.Quantity, product.Price);
}
await _orderWriteRepository.AddAsync(order);
await _orderWriteRepository.SaveChangesAsync();
await transaction.CommitAsync();
return order.Id;
}
catch
{
await transaction.RollbackAsync();
throw;
}
}
}
public static class MappingConfig
{
public static void ConfigureMappings()
{
TypeAdapterConfig.GlobalSettings.Scan(typeof(Product).Assembly);
// Custom mapping configuration
TypeAdapterConfig<Product, ProductDto>
.NewConfig()
.Map(dest => dest.CategoryName, src => src.Category.Name)
.Map(dest => dest.IsOnSale, src => src.DiscountPercentage > 0);
TypeAdapterConfig<Order, OrderSummaryDto>
.NewConfig()
.Map(dest => dest.TotalAmount, src => src.Items.Sum(i => i.TotalPrice))
.Map(dest => dest.ItemCount, src => src.Items.Count);
}
}
// Register in Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddMapster();
MappingConfig.ConfigureMappings();
services.AddGenericRepositories<AppDbContext>();
}
public interface IProductRepository : IRepository<Product>
{
Task<IEnumerable<Product>> GetProductsByCategoryAsync(string category);
Task<bool> ExistsBySkuAsync(string sku);
Task<Product?> GetProductWithCategoryAsync(Guid id);
}
public class ProductRepository : Repository<Product>, IProductRepository
{
public ProductRepository(DbContext dbContext, IEnumerable<IMapper>? mappers = null)
: base(dbContext, mappers)
{
}
public async Task<IEnumerable<Product>> GetProductsByCategoryAsync(string category)
{
return await Gets()
.Where(p => p.Category == category && p.IsActive)
.OrderBy(p => p.Name)
.ToListAsync();
}
public async Task<bool> ExistsBySkuAsync(string sku)
{
return await Gets().AnyAsync(p => p.Sku == sku);
}
public async Task<Product?> GetProductWithCategoryAsync(Guid id)
{
return await Gets()
.Include(p => p.Category)
.FirstOrDefaultAsync(p => p.Id == id);
}
}
// Register custom repository
services.AddScoped<IProductRepository, ProductRepository>();
Repository<TEntity> - Full repository implementation combining read and write operationsReadRepository<TEntity> - Read-only repository implementationWriteRepository<TEntity> - Write-only repository implementationAddGenericRepositories<TDbContext>() - Register all generic repositories with specified DbContextGets() - Get IQueryable for building complex queriesGetDto<TModel>(filter?) - Get projected DTOs with optional filteringFindAsync(id) - Find entity by primary keyFindAsync(filter) - Find first entity matching filterAddAsync(entity) - Add single entityAddRangeAsync(entities) - Add multiple entitiesUpdateAsync(entity) - Update entityDeleteAsync(entity) - Delete entitySaveChangesAsync() - Persist changes to databaseBeginTransactionAsync() - Start database transactionEntry(entity) - Get EntityEntry for change trackingpublic interface IUnitOfWork
{
IRepository<Product> Products { get; }
IRepository<Customer> Customers { get; }
IRepository<Order> Orders { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
}
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
private readonly IServiceProvider _serviceProvider;
public UnitOfWork(AppDbContext context, IServiceProvider serviceProvider)
{
_context = context;
_serviceProvider = serviceProvider;
}
public IRepository<Product> Products => _serviceProvider.GetRequiredService<IRepository<Product>>();
public IRepository<Customer> Customers => _serviceProvider.GetRequiredService<IRepository<Customer>>();
public IRepository<Order> Orders => _serviceProvider.GetRequiredService<IRepository<Order>>();
public Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
=> _context.SaveChangesAsync(cancellationToken);
public Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default)
=> _context.Database.BeginTransactionAsync(cancellationToken);
}
public class BulkOperationService
{
private readonly IWriteRepository<Product> _productRepository;
public BulkOperationService(IWriteRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public async Task BulkUpdatePricesAsync(Dictionary<Guid, decimal> priceUpdates)
{
using var transaction = await _productRepository.BeginTransactionAsync();
try
{
var productIds = priceUpdates.Keys.ToList();
var products = await _productRepository.Gets()
.Where(p => productIds.Contains(p.Id))
.ToListAsync();
foreach (var product in products)
{
if (priceUpdates.TryGetValue(product.Id, out var newPrice))
{
product.UpdatePrice(newPrice);
}
}
await _productRepository.UpdateRangeAsync(products);
await _productRepository.SaveChangesAsync();
await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
throw;
}
}
public async Task BulkDeleteByIdsAsync(List<Guid> ids)
{
var entities = await _productRepository.Gets()
.Where(p => ids.Contains(p.Id))
.ToListAsync();
if (entities.Any())
{
await _productRepository.DeleteRangeAsync(entities);
await _productRepository.SaveChangesAsync();
}
}
}
public class CachedProductRepository : IReadRepository<Product>
{
private readonly IReadRepository<Product> _repository;
private readonly IMemoryCache _cache;
private readonly TimeSpan _cacheExpiry = TimeSpan.FromMinutes(15);
public CachedProductRepository(IReadRepository<Product> repository, IMemoryCache cache)
{
_repository = repository;
_cache = cache;
}
public async ValueTask<Product?> FindAsync(object keyValue, CancellationToken cancellationToken = default)
{
var cacheKey = $"product:{keyValue}";
if (_cache.TryGetValue(cacheKey, out Product? cachedProduct))
return cachedProduct;
var product = await _repository.FindAsync(keyValue, cancellationToken);
if (product != null)
{
_cache.Set(cacheKey, product, _cacheExpiry);
}
return product;
}
public IQueryable<Product> Gets() => _repository.Gets();
public IQueryable<TModel> GetDto<TModel>(Expression<Func<Product, bool>>? filter = null)
where TModel : class => _repository.GetDto<TModel>(filter);
// Implement other methods...
}
public class GetProductQueryHandler : IRequestHandler<GetProductQuery, ProductDto?>
{
private readonly IReadRepository<Product> _repository;
public GetProductQueryHandler(IReadRepository<Product> repository)
{
_repository = repository;
}
public async Task<ProductDto?> Handle(GetProductQuery request, CancellationToken cancellationToken)
{
return await _repository
.GetDto<ProductDto>(p => p.Id == request.Id)
.FirstOrDefaultAsync(cancellationToken);
}
}
public class CreateProductCommandHandler : IRequestHandler<CreateProductCommand, Guid>
{
private readonly IWriteRepository<Product> _repository;
public CreateProductCommandHandler(IWriteRepository<Product> repository)
{
_repository = repository;
}
public async Task<Guid> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
var product = new Product(request.Name, request.Price, request.Category);
await _repository.AddAsync(product, cancellationToken);
await _repository.SaveChangesAsync(cancellationToken);
return product.Id;
}
}
GetDto<T>() for read-only queries to minimize data transferGets() returns IQueryable for efficient query compositionSee the main for guidelines on how to contribute to this project.
This project is licensed under the .
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. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 9.5.39 | 462 | 11/13/2025 |
| 9.5.38 | 277 | 11/6/2025 |
| 9.5.37 | 260 | 11/5/2025 |
| 9.5.36 | 255 | 11/5/2025 |
| 9.5.35 | 253 | 11/4/2025 |
| 9.5.34 | 256 | 11/4/2025 |
| 9.5.33 | 274 | 11/3/2025 |
| 9.5.32 | 256 | 11/3/2025 |
| 9.5.31 | 228 | 10/31/2025 |
| 9.5.30 | 253 | 10/31/2025 |
| 9.5.29 | 269 | 10/30/2025 |
| 9.5.28 | 245 | 10/27/2025 |
| 9.5.27 | 253 | 10/27/2025 |
| 9.5.26 | 243 | 10/27/2025 |
| 9.5.25 | 244 | 10/26/2025 |
| 9.5.24 | 178 | 10/25/2025 |
| 9.5.23 | 176 | 10/25/2025 |
| 9.5.22 | 182 | 10/25/2025 |
| 9.5.21 | 262 | 10/24/2025 |
| 9.5.20 | 261 | 10/23/2025 |